如何在每次改造 API 调用时自动显示进度条?

How to automatically show Progress Bar on each retrofit API call?

如何实现在每个 Retrofit 2.0 API 调用中显示进度条,而不必在每个 activity 中显示进度条,显示并关闭。进度条应显示 每当 一个 API 被击中时,当我们在 onResponse 上收到响应或调用 onFailure 时它应该消失。

我试过这个:

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 调用时,这段代码都必须复制粘贴到各处。我不想重复代码。

回调的基础 class 可以派上用场。

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
        });

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

public void showDialog() {

    if(mProgressDialog != null && !mProgressDialog.isShowing())
        mProgressDialog.show();
}

public void hideDialog() {

    if(mProgressDialog != null && mProgressDialog.isShowing())
        mProgressDialog.dismiss();
}

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

教程中的示例:

   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);
}

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

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

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);
    }

}
}

希望对你有所帮助

无耻宣传

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

你可以这样做:

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

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

如果您希望一个进度条统领所有进度条,根据您的应用程序结构,您可以通过多种方式实现它:

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

RxLoading 还支持空状态和错误状态(具有 built-in 重试机制,因此请确保也检查此选项)

您可以在 GitHub page 上找到更多信息。