web-dev-qa-db-ja.com

POST with Android Retrofit

AndroidプログラミングとRetrofitでの作業が初めてです。このトピックについて多くの研究を行ってきましたが、自分のニーズに合ったソリューションを見つけることができませんでした。私たちのAPIを使用して、POSTリクエストを作成しようとしています。次の非レトロフィットコードでこれを達成しました。

    private class ProcessLogin extends AsyncTask<Void, String, JSONObject> {
    private ProgressDialog pDialog;
    String email,password;

    protected void onPreExecute() {
        super.onPreExecute();
        inputEmail = (EditText) findViewById(R.id.email);
        inputPassword = (EditText) findViewById(R.id.password);
        email = inputEmail.getText().toString();
        password = inputPassword.getText().toString();
        pDialog = new ProgressDialog(LoginActivity.this);
        pDialog.setTitle("Contacting Servers");
        pDialog.setMessage("Logging in ...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    protected JSONObject doInBackground(Void... params) {
        HttpURLConnection connection;
        OutputStreamWriter request = null;
        URL url = null;   
        String response = null;         
        String parameters = "username="+email+"&password="+password;  
        try
        {
            url = new URL("http://.../api/login");
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestMethod("POST");    

            request = new OutputStreamWriter(connection.getOutputStream());
            request.write(parameters);
            request.flush();
            request.close();            
            String line = "";               
            InputStreamReader isr = new InputStreamReader(connection.getInputStream());
            BufferedReader reader = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            while ((line = reader.readLine()) != null)
            {
                sb.append(line + "\n");
            }
            // Response from server after login process will be stored in response variable.                
            response = sb.toString();
            // You can perform UI operations here
            isr.close();
            reader.close();
        }
        catch(IOException e)
        {
            // Error
        }
        System.out.println(response);
        JSONObject jObj = null;        
        // Try to parse the string to a JSON Object
        try {
            jObj = new JSONObject(response);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        // Return the JSONObject
        return jObj;
    }

    protected void onPostExecute(JSONObject json) {
        String status = (String) json.optJSONArray("users").optJSONObject(0).optJSONObject("user").optString("login");
        pDialog.dismiss();
        if (status.equals("Failed")) {
            loginMessage.setText("Login Failed");   
        }
        else if (status.equals("Success")) {
            loginMessage.setText("Success!");   
            startActivity(new Intent(getApplicationContext(), DActivity.class));
        }

    }
}

今、Retrofitを使用して同じ結果を取得しようとしていますが、コールバックを使用してAPIからJSONを取得する方法がわかりません(この呼び出しは非同期に行われると仮定していますか?):

次のメソッドを使用してインターフェイスを作成しました。

    @FormUrlEncoded
@POST("/login")
public void login(@Field("username") String username, @Field("password") String password, Callback<JSONObject> callback);

そして、アクティビティのonCreateメソッドでRestAdapterなどをインスタンス化しました。ユーザーが「ログイン」ボタンを押すと(ユーザー名とパスワードを入力した後)、ボタンのonClickメソッド内で次が呼び出されます。

    service.login(email, password, new Callback<JSONObject>() { 
            @Override
            public void failure(final RetrofitError error) {
                Android.util.Log.i("example", "Error, body: " + error.getBody().toString());
            }
            @Override
            public void success(JSONObject arg0, Response arg1) {

            }
        }
        );

しかし、これは意図したとおりに機能せず、実際にこれに正しく近づいているとは思いません。 POST=をサーバーに送信すると、そのユーザーに関するJSON形式のデータのブロックが返されます。誰かが私を正しい方向に向けることができれば、本当に感謝します。 前もって感謝します

22
mike

Retrofitの利点の1つは、JSONを自分で解析する必要がないことです。次のようなものが必要です。

service.login(email, password, new Callback<User>() { 
        @Override
        public void failure(final RetrofitError error) {
            Android.util.Log.i("example", "Error, body: " + error.getBody().toString());
        }
        @Override
        public void success(User user, Response response) {
            // Do something with the User object returned
        }
    }
);

UserはPOJOです

public class User {
    private String name;
    private String email;
    // ... etc.
}

返されたJSONには、Userクラスに一致するフィールドがあります。

{
  "name": "Bob User",
  "email": "[email protected]",
  ...
}

カスタム解析が必要な場合は、RESTアダプターのコンバーターを 。setConverter(Converter converter)

オブジェクトのシリアル化と逆シリアル化に使用されるコンバーター。

21
blahdiblah

Retrofitは@POST@FormUrlEncodedに問題があるようです。同期を行う場合はうまく機能しますが、非同期の場合は失敗します。

@mike問題が逆シリアル化オブジェクトである場合、ユーザークラスは

public class User {
     @SerializedName("name")
     String name;

     @SerializedName("email")
     String email;
}

インターフェースクラス

@FormUrlEncoded
@POST("/login")
void login(@Field("username") String username, @Field("password") String password, Callback<User> callback);

または

@FormUrlEncoded
@POST("/login")
void login(@Field("username") String username, @Field("password") String password, Callback<UserResponse> callback);

どこで

public class UserResponse {

@SerializedName("email")
String email;

@SerializedName("name")
String name;

}
8
khaintt