【问题标题】:How to automatically show Progress Bar on each retrofit API call?如何在每次改造 API 调用时自动显示进度条?
【发布时间】:2016-06-03 18:48:54
【问题描述】:

如何实现在每个Retrofit 2.0 API 调用上显示一个进度条,而不必在每个活动中创建一个进度条,显示它并关闭它。进度条应该无论何时显示一个 API,当我们收到对 onResponseonFailure 的响应时它应该关闭。

我试过这个:

ProgressDialog mProgressDialog = new ProgressDialog(this);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage("Loading...");
mProgressDialog.show();
retrofitService.login(new SignInRequest(email, password),
                new Callback<SignInResponse>() {
         @Override
         public void onResponse(Call<SignInResponse> call, Response<SignInResponse> response) {

              if (mProgressDialog.isShowing())
                  mProgressDialog.dismiss();
          }

         @Override
         public void onFailure(Call<SignInResponse> call, Throwable t) {
              if (mProgressDialog.isShowing())
                  mProgressDialog.dismiss();
          }
 });

但是每当我进行 API 调用时,这段代码都必须复制粘贴到任何地方。我不想要重复的代码。

【问题讨论】:

  • 创建一个基础活动来完成所有这些工作?
  • 请举个例子..
  • 使用基本回调或拦截器

标签: android android-progressbar retrofit2


【解决方案1】:

回调的基类会很方便。

class BaseCallBack implements CallBacks<T>{
  @Override
     public void onResponse(Call<T> call, Response<T> response) {

          if (mProgressDialog.isShowing())
              mProgressDialog.dismiss();
      }

     @Override
     public void onFailure(Call<SignInResponse> call, Throwable t) {
          if (mProgressDialog.isShowing())
              mProgressDialog.dismiss();
      }
}

当您发送请求时:

retrofitService.login(new SignInRequest(email, password), new MyCallback<SignInResponse>() {
     @Override
     public void onResponse(Call<SignInResponse> call, Response<SignInResponse> response) {
          super.onResponse(call, response);
          //do more on response
      }

     @Override
     public void onFailure(Call<SignInResponse> call, Throwable t) {
          super.onFailure(call, t);
          /* Do more on failure. For example: give a reason why the
           request failed*/ 
      }
 });

编辑 2019 - 使用 RXjava 适配器:

   getUsers()
        .subscribeOn(AndroidSchedulers.io()) //run request in the background and deliver response to the main thread aka UI thread
        .observeOn(AndroidSchedulers.mainThread())
        .doOnSubscribe(() -> showLoading())
        .doOnTerminate(() -> hideLoading())
        .subscribe(data -> {
            //request is successful
        }, error -> {
            //show error
        });

【讨论】:

    【解决方案2】:

    正如@Sourabh 所建议的,我最终使用了一个 Base 活动并在每次 API 调用期间调用了简单的方法。在BaseActivity

    public void showDialog() {
    
        if(mProgressDialog != null && !mProgressDialog.isShowing())
            mProgressDialog.show();
    }
    
    public void hideDialog() {
    
        if(mProgressDialog != null && mProgressDialog.isShowing())
            mProgressDialog.dismiss();
    }
    

    在您的子活动中,您可以直接调用showDialog()hideDialog() 来显示和关闭对话框。

    【讨论】:

      【解决方案3】:

      根据 Shubham 和 peter 的回答,我写了一个这样的类:

      class CustomCallBack<T> implements Callback<T> {
      
      private ProgressDialog mProgressDialog;
      Context context;
      
      CustomCallBack(Context context) {
          this.context = context;
          mProgressDialog = new ProgressDialog(context);
          ((Activity) context).getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                  WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
          mProgressDialog.setIndeterminate(true);
          mProgressDialog.setMessage("Loading...");
          mProgressDialog.setCanceledOnTouchOutside(false);
          mProgressDialog.show();
      
      }
      
      @Override
      public void onResponse(Call<T> call, Response<T> response) {
          if (mProgressDialog.isShowing()) {
              mProgressDialog.dismiss();
              ((Activity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
          }
      
      }
      
      @Override
      public void onFailure(Call<T> call, Throwable t) {
          if (mProgressDialog.isShowing()) {
              mProgressDialog.dismiss();
              ((Activity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
          }
      
      }
      }
      

      希望对你有帮助。

      【讨论】:

        【解决方案4】:

        无耻宣传

        我为此创建了RxLoading library,它可以做到这一点以及更多,

        你可以这样做:

        networkCall().compose(RxLoading.<>create(loadingLayout)).subscribe(...);
        

        它由 2 个类组成,一个自定义视图 (loadingLayout) 和 RxLoading,它是一个 transformer,将它们粘合在一起,您可以选择同时使用它们或其中之一。

        如果您想要一个进度条来统治所有这些,您可以根据应用程序的结构来实现它:

        • 一个Activity多个fragment -> 只需在主屏幕中放一个loadingLayout,并告诉它在加载时隐藏fragment布局
        • 多个活动:创建一个所有使用的基本活动,并向所有视图注入 loadingLayout
        • 您还可以为进度条创建一个特殊的对话框或活动,并使用 RxLoading 界面来显示和隐藏它。

        RxLoading 还支持空和错误状态(具有内置重试机制,因此请务必检查此选项)

        您可以通过GitHub page了解更多信息。

        【讨论】:

          【解决方案5】:

          教程示例:

             protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
              requestWindowFeature(Window.FEATURE_PROGRESS);
              ArrayAdapter<Question> arrayAdapter =
                      new ArrayAdapter<Question>(this,
                              android.R.layout.simple_list_item_1,
                              android.R.id.text1,
                              new ArrayList<Question>());
              setListAdapter(arrayAdapter);
              setProgressBarIndeterminateVisibility(true);
              setProgressBarVisibility(true);
          }
          

          教程链接:http://www.vogella.com/tutorials/Retrofit/article.html

          【讨论】:

          • 这种方法自 API 21 起已被弃用。Rx 有什么替代方案吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-28
          • 2021-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多