【问题标题】:AsyncTask already finished [duplicate]AsyncTask 已经完成[重复]
【发布时间】:2017-10-22 14:21:00
【问题描述】:

如何捕捉 AsyncTask 完成的时刻? 我有扩展 AsyncTask 的 ProfileUpdate 类,并从另一个活动中调用此方法,并且在我需要更新我的数据之后。如何知道 asynctask 完成了? 我的 asynctask 方法在另一个类中而不是在活动类中!!!

这是我在活动中的 onRefresh 方法:

@Override
public void onRefresh() {
    if (!AlertView.isInternetAvailable(getContext())) {
        swipeLayout.setRefreshing(false);
        Toast.makeText(getContext(), Messages.CONNECTION_ERROR + ": " + Messages.NO_INTERNET, Toast.LENGTH_SHORT).show();
    } else {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                new UpdateProfile(getActivity(), swipeLayout, sharedPreferences.getString(Constants.TOKEN, ""), user.getIin()).execute(Urls.GET_USER);
            }
        });
        profileDefaults();
    }
}

这里是我的 AsyncTask 方法:

public class UpdateProfile extends AsyncTask <String, Void, String> {
private Activity activity;
private SwipeRefreshLayout swipeRefreshLayout;
private String token;
private String userIin;
private SharedPreferences sharedPreferences;

public UpdateProfile(Activity activity, SwipeRefreshLayout swipeRefreshLayout, String token, String userIin) {
    this.activity = activity;
    this.swipeRefreshLayout = swipeRefreshLayout;
    this.token = token;
    this.userIin = userIin;
    sharedPreferences = this.activity.getSharedPreferences(Constants.PROJECT, Context.MODE_PRIVATE);
}

@Override
protected String doInBackground(String... params) {
    URL url = null;
    try {
        url = new URL(params[0]);
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            RequestBody body = new FormBody.Builder()
                    .add("iin", userIin)
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .addHeader(Constants.AUTH_TOKEN, token)
                    .post(body)
                    .build();
            Response responses = null;
            try {
                responses = okHttpClient.newCall(request).execute();
            } catch (Exception e) {
                AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
            }

            assert responses != null;
            return responses.body().string();

        } catch (Exception e) {
            AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
        }
    } catch (Exception e) {
        AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
    }
    return null;
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    try {
        JSONObject jsonObject = new JSONObject(s);
        int code = Integer.valueOf(jsonObject.getString(Constants.CODE));
        if (code == Codes.OK) {
            Toast.makeText(activity, "Данные обновлены", Toast.LENGTH_SHORT).show();

            String userHeader = jsonObject.getString("user");
            JSONObject userInfo = new JSONObject(userHeader);

            String mobilePhone = userInfo.getString(SingletonConstants.MOBILE_PHONE);
            Boolean isActive = userInfo.getBoolean(SingletonConstants.IS_ACTIVE);
            Boolean signedAgreement = userInfo.getBoolean(SingletonConstants.SIGNED_AGREEMENT);
            Boolean esfEntered = userInfo.getBoolean(SingletonConstants.ESF_ENTERED);
            String address = userInfo.getString(SingletonConstants.ADDRESS);
            String iin = userInfo.getString(SingletonConstants.IIN);
            String certExpDate = userInfo.getString(SingletonConstants.CERT_EXP_DATE);
            String firstName = userInfo.getString(SingletonConstants.FIRST_NAME);
            String middleName = userInfo.getString(SingletonConstants.MIDDLE_NAME);
            String workPhone = userInfo.getString(SingletonConstants.WORK_PHONE);
            String secondName = userInfo.getString(SingletonConstants.SECOND_NAME);
            String avatarUrl = userInfo.getString(SingletonConstants.AVATAR_URL);;
            String secondEmail = userInfo.getString(SingletonConstants.SECOND_EMAIL);
            String email = userInfo.getString(SingletonConstants.EMAIL);

            User newUser = new User(mobilePhone, isActive, signedAgreement, esfEntered, address, iin, certExpDate, firstName, middleName, workPhone, secondName, avatarUrl, secondEmail, email);

            Gson gson = new Gson ();
            String userGson = gson.toJson (newUser);
            sharedPreferences.edit().putString(SingletonConstants.USER, userGson).apply();
            swipeRefreshLayout.setRefreshing(false);

        } else {
            AlertView.showAlertView(activity, Messages.ERROR, jsonObject.getString(Constants.MESSAGE), Messages.OK);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

如何调用 profileDefaults()?这是我的活动。而且我需要在 onPostExecute 之后调用它!

【问题讨论】:

  • 为什么不让处理异步任务的类成为消耗它的活动的内部类呢?这是我以前用过的模式,从来没有遇到过你的问题。
  • @TimBiegeleisen 是的,我当然可以在我的活动中编写这个 asyncTask,但是我在这个活动中有几个 asynctask 方法,而且代码真的很多,我只想将每个 asynctask 方法划分为不同的类
  • 你能传递一个对调用活动的引用,然后使用它分配一些类级别的变量吗?
  • @TimBiegeleisen 这个方法我来更新配置文件,这里我有用户类,它有很多数据,我认为每次都发送构造函数不太舒服

标签: java android android-asynctask


【解决方案1】:

一种更简洁的方法是将接口用作侦听器。 创建这个接口:

public interface OnAsyncFinished{
    void onAsyncFinished(Object o);
}

将接口作为参数添加到 AsyncTaskClass 构造函数中:

private OnAsyncFinished onAsyncFinished;
public UpdateProfile(..., OnAsyncFinished onAsyncFinished) {
   ...
   this.onAsyncFinished = onAsyncFinished;
}
...
@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    onAsyncFinished.onAsyncFinished(s); //This will notifiy the method on main activity, and you can now resume the work there
    ...
}

在你的主要活动中实现接口:

public MainActivity extends Activity implements OnAsyncFinished {
     @Override
     public void onAsyncFinished(Object o) {
         //This will get called after onPostExecute, do what u want with the object you got from onPostExecute, json or string in ur example
         profileDefaults(); //call ur function
     }
}

编辑: 在主活动中创建异步任务时,在构造函数中传递this,如下所示:

        @Override
        public void run() {
            new UpdateProfile(..., this).execute(Urls.GET_USER);
        }

【讨论】:

  • 如何在构造函数中传递 onAsyncFinished?
  • 我会编辑我的答案
  • 以及如何将其放入 Fragment?
  • 同理,实现fragment中的接口,创建异步任务时传入this
  • 还有一个问题,如果我尝试多次调用此方法?它还会工作吗?我认为没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 2011-10-18
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 2018-07-14
相关资源
最近更新 更多