在 Android 中使用 Retrofit

新手上路,请多包涵

我有一个有 3 个活动的 android 应用程序:

  1. 登录活动
  2. 显示与用户有关的所有任务的任务活动(使用阵列适配器填充)
  3. 单击列表中的任务产生的 task_details 活动

我必须使用 REST Apis。到目前为止,我所做的研究指导我使用 Retrofit。我检查了如何使用它并发现:

  1. 在主活动中设置基本 URL(我的是登录活动)
  2. 我需要创建一个 API 类并使用注释定义我的函数。
  3. 在 Activity 中使用类 Rest Adapter 并定义回调。

如果我的应用程序是一个单一的活动应用程序,我会处理我的 MainActivity.java 中的所有内容,但我不知道如何以及在哪里放置步骤 1、2、3 中的所有代码以用于我的 3 个活动。你能不能通过告诉我如何在我的应用程序中使用 Retrofit 来提供帮助。非常感谢。

具体来说,我需要网络调用: 1. 登录用户 2. 获取用户的所有任务。对于两者,我都会使用给定的 REST api。

 *********************************************
          Calling Api USing Retrofit
*********************************************
**Dependancies** :-
      implementation 'com.android.support:recyclerview-v7:27.1.1'
        implementation 'com.squareup.picasso:picasso:2.5.2'
        implementation 'com.android.support:cardview-v7:27.1.1'
    enter code here
**Model**
use the Pozo class

**Api Call**
 -> getLogin()    // use the method

  //API call for Login
    private void getLogin()
    {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
        AsyncHttpClient client = new AsyncHttpClient();
        RequestParams requestParams = new RequestParams();
        requestParams.put("email_id", edit_email.getText().toString());
        requestParams.put("password", edit_password.getText().toString());
        Log.e("", "LOGIN URL==>" + Urls.LOGIN + requestParams);
        Log.d("device_token", "Device_ Token" + FirebaseInstanceId.getInstance().getToken());
        client.post(Urls.LOGIN, requestParams, new JsonHttpResponseHandler() {
            @Override
            public void onStart() {
                super.onStart();
                ShowProgress();
            }

            @Override
            public void onFinish() {
                super.onFinish();
                Hideprogress();

            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                super.onSuccess(statusCode, headers, response);
                Log.e("", "Login RESPONSE-" + response);
                Login login = new Gson().fromJson(String.valueOf(response), Login.class);
                edit_email.setText("");
                edit_password.setText("");
                if (login.getStatus().equals("true")) {
                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
                    MDToast mdToast = MDToast.makeText(SignInActivity.this, String.valueOf("User Login Successfully!"),
                            MDToast.LENGTH_SHORT, MDToast.TYPE_SUCCESS);
                    mdToast.show();
                    Utils.WriteSharePrefrence(SignInActivity.this, Util_Main.Constant.EMAIL, login.getData().getEmailId());
                    Utils.WriteSharePrefrence(SignInActivity.this, Constant.USERID, login.getData().getId());

                    Utils.WriteSharePrefrence(SignInActivity.this, Constant.USERNAME, login.getData().getFirstName());
                    Utils.WriteSharePrefrence(SignInActivity.this, Constant.PROFILE, login.getData().getProfileImage());
                    hideKeyboard(SignInActivity.this);
                    Intent intent = new Intent(SignInActivity.this, DashboardActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(intent);
                    finish();
                } else {
                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
                    MDToast mdToast = MDToast.makeText(SignInActivity.this, String.valueOf("Login Denied"),
                            MDToast.LENGTH_SHORT, MDToast.TYPE_ERROR);
                    mdToast.show();
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                super.onFailure(statusCode, headers, responseString, throwable);
                Log.e("", throwable.getMessage());
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
                MDToast mdToast = MDToast.makeText(SignInActivity.this, "Something went wrong",
                        MDToast.LENGTH_SHORT, MDToast.TYPE_ERROR);
                mdToast.show();
            }
        });
    }

原文由 Stack Man 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 569
2 个回答

使用 Retrofit 非常简单明了。

首先,您需要为您的项目添加改造,例如 Gradle 构建系统。

 compile 'com.squareup.retrofit:retrofit:1.7.1' |

另一种方法是您可以下载 .jar 并将其放入您的 libs 文件夹中。

然后,您需要定义接口,Retrofit 将使用这些接口对您的 REST 端点进行 API 调用。例如对于用户:

 public interface YourUsersApi {

   //You can use rx.java for sophisticated composition of requests
   @GET("/users/{user}")
   public Observable<SomeUserModel> fetchUser(@Path("user") String user);

   //or you can just get your model if you use json api
   @GET("/users/{user}")
   public SomeUserModel fetchUser(@Path("user") String user);

   //or if there are some special cases you can process your response manually
   @GET("/users/{user}")
   public Response fetchUser(@Path("user") String user);

}

好的。现在您已经定义了 API 接口,您可以尝试使用它了。

首先,您需要创建一个 RestAdapter 实例并设置 API 后端的基本 url。这也很简单:

 RestAdapter restAdapter = new RestAdapter.Builder()
   .setEndpoint("https://yourserveraddress.com")
    .build();

YourUsersApi yourUsersApi = restAdapter.create(YourUsersApi.class);

在这里,Retrofit 将从界面读取您的信息,并在后台根据您提供的元信息创建 RestHandler ,它实际上将执行 HTTP 请求。

然后在幕后,一旦收到响应,在 json api 的情况下,您的数据将使用 Gson 库转换为您的模型,因此您应该意识到 Gson 中存在的限制实际上存在于 Retrofit 中。

要扩展/覆盖序列化器/反序列化您的响应数据到您的模型的过程,您可能需要提供自定义序列化器/反序列化器以进行改造。

这里需要实现 Converter 接口,实现 fromBody()toBody() 两个方法。

这是例子:

 public class SomeCustomRetrofitConverter implements Converter {

    private GsonBuilder gb;

    public SomeCustomRetrofitConverter() {
        gb = new GsonBuilder();

        //register your cursom custom type serialisers/deserialisers if needed
        gb.registerTypeAdapter(SomeCutsomType.class, new SomeCutsomTypeDeserializer());
    }

    public static final String ENCODING = "UTF-8";

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        String charset = "UTF-8";
        if (body.mimeType() != null) {
            charset = MimeUtil.parseCharset(body.mimeType());
        }
        InputStreamReader isr = null;
        try {
           isr = new InputStreamReader(body.in(), charset);
           Gson gson = gb.create();
           return gson.fromJson(isr, type);
        } catch (IOException e) {
            throw new ConversionException(e);
        } catch (JsonParseException e) {
            throw new ConversionException(e);
        } finally {
            if (isr != null) {
                   try {
                      isr.close();
                   } catch (IOException ignored) {
                }
            }
        }
    }

    @Override
    public TypedOutput toBody(Object object) {
        try {
            Gson gson = gb.create();
            return new JsonTypedOutput(gson.toJson(object).getBytes(ENCODING), ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw new AssertionError(e);
        }
     }

    private static class JsonTypedOutput implements TypedOutput {
        private final byte[] jsonBytes;
        private final String mimeType;

        JsonTypedOutput(byte[] jsonBytes, String encode) {
            this.jsonBytes = jsonBytes;
            this.mimeType = "application/json; charset=" + encode;
        }

        @Override
        public String fileName() {
            return null;
        }

       @Override
       public String mimeType() {
           return mimeType;
       }

       @Override
       public long length() {
          return jsonBytes.length;
       }

       @Override
       public void writeTo(OutputStream out) throws IOException {
           out.write(jsonBytes);
       }
    }
 }

现在你需要启用你的自定义适配器,如果在构建 RestAdapter 时需要使用 setConverter()

好的。现在您知道了如何将数据从服务器获取到您的 Android 应用程序。但是您需要以某种方式管理您的数据并在正确的位置调用 REST 调用。在那里,我建议使用 android Service 或 AsyncTask 或 loader 或 rx.java 来查询后台线程上的数据,以免阻塞您的 UI。

所以现在你可以找到最合适的地方打电话

SomeUserModel yourUser = yourUsersApi.fetchUser("someUsers")

获取您的远程数据。

原文由 Artemis 发布,翻译遵循 CC BY-SA 3.0 许可协议

我刚刚使用 retrofit 几个星期,起初我发现它很难在我的应用程序中使用。我想与您分享在您的应用程序中使用改造的最简单方法。然后,如果您已经很好地掌握了改造,您可以增强您的代码(将您的 ui 与 api 分开并使用回调)并且可能从上面的帖子中获得一些技术。

在您的应用程序中,您有登录、用于任务列表的活动和用于查看详细任务的活动。

首先,您需要在您的应用程序中添加改造,有 2 种方法,请按照上面的@artemis 帖子进行操作。

Retrofit 使用接口作为您的 API。所以,创建一个接口类。

 public interface MyApi{

/*LOGIN*/
@GET("/api_reciever/login") //your login function in your api
public void login(@Query("username") String username,@Query("password") String password,Callback<String> calback); //this is for your login, and you can used String as response or you can use a POJO, retrofit is very rubust to convert JSON to POJO

/*GET LIST*/
@GET("/api_reciever/getlist") //a function in your api to get all the list
public void getTaskList(@Query("user_uuid") String user_uuid,Callback<ArrayList<Task>> callback); //this is an example of response POJO - make sure your variable name is the same with your json tagging

/*GET LIST*/
@GET("/api_reciever/getlistdetails") //a function in your api to get all the list
public void getTaskDetail(@Query("task_uuid") String task_uuid,Callback<Task> callback);   //this is an example of response POJO - make sure your variable name is the same with your json tagging

}

创建另一个接口类来保存你的 api 的所有 BASE ADDRESS

 public interface Constants{
   public String URL = "www.yoururl.com"
}

在您的登录活动中创建一个方法来处理改造

private void myLogin(String username,String password){

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint(Constants.URL)  //call your base url
    .build();

MyApi mylogin = restAdapter.create(MyApi.class); //this is how retrofit create your api
mylogin.login(username,password,new Callback<String>() {
        @Override
        public void success(String s, Response response) {
            //process your response if login successfull you can call Intent and launch your main activity

        }

        @Override
        public void failure(RetrofitError retrofitError) {
            retrofitError.printStackTrace(); //to see if you have errors
        }
    });
}

在您的 MainActivityList 中

private void myList(String user_uuid){

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint(Constants.URL)  //call your base url
    .build();

MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api
mytask.getTaskDetail(user_uuid,new Callback<Task>>() {
        @Override
        public void success(ArrayList<Task> list, Response response) {
            //process your response if successful load the list in your listview adapter

        }

        @Override
        public void failure(RetrofitError retrofitError) {
            retrofitError.printStackTrace(); //to see if you have errors
        }
    });
}

在您的详细列表中

private void myDetailed(String task_uuid){

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint(Constants.URL)  //call your base url
    .build();

MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api
mytask.getTaskList(task_uuid,new Callback<Task>() {
        @Override
        public void success(Task task, Response response) {
            //process your response if successful do what you want in your task

        }

        @Override
        public void failure(RetrofitError retrofitError) {
            retrofitError.printStackTrace(); //to see if you have errors
        }
    });
}

希望这对您有所帮助,尽管它确实是使用改装的最简单方法。

原文由 chkm8 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题