我正在尝试使用更安全的异步任务来重构我的片段密码,因为我注意到偶尔发生了一些崩溃。现在,经过一些搜索,我受过更好的教育,我发现我的主要问题是从异步任务本身访问活动或片段变量。
我将每个异步任务分成单个类,这些类实现了对调用它们的片段或活动的接口回调。例如:
public class LoginFragment extends Fragment implements RequestForgotPassword {
...
//On Forgot Password click
new AsyncForgotPassword(LoginFragment.this, mEmail).execute();
...
@Override
public void onForgotPasswordResult(Result result)
{
if(isAdded())
{
if (result == Result.SUCCESS)
Toast.makeText(getActivity(), "An email has been sent to your account to assist in recovering your password", Toast.LENGTH_LONG).show();
else
Toast.makeText(getActivity(), "We don't have any record of that registered email, sorry! Please try again", Toast.LENGTH_LONG).show();
}
}
...
}
OnTaskCompleted.java
public interface OnTaskCompleted {
enum Result{SUCCESS, FAILURE};
}
RequestForgotPassword.java
public interface RequestForgotPassword extends OnTaskCompleted {
void onForgotPasswordResult(Result result);
}
AsyncForgotPassword.java
public class AsyncForgotPassword extends AsyncTask<Void, Void, JSONObject> {
private RequestForgotPassword mRequest;
private String mEmail;
public AsyncForgotPassword(RequestForgotPassword request, String email)
{
mRequest = request;
mEmail = email;
}
@Override
protected JSONObject doInBackground(Void... params) {
ServerFunctions serverFunctions = new ServerFunctions();
return serverFunctions.forgotPassword(mEmail);
}
@Override
protected void onPostExecute(JSONObject obj) {
try {
JSONObject json1 = obj.getJSONObject("response");
if (json1.getString("success").matches("1")) {
mRequest.onForgotPasswordResult(OnTaskCompleted.Result.SUCCESS);
} else {
mRequest.onForgotPasswordResult(OnTaskCompleted.Result.FAILURE);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
所以基本上我认为如果大多数异步任务都是这样编写的话会很好。许多将以进度对话为特色,可以长时间运行,或者与调用片段等进行有意义的交互。我发现了一些非常有趣的讨论here,here,here和here让我接近这个设置。
我在第一个链接的答案(2010年的书面回答)中对Dianne的代码的理解是,它确保从异步任务访问时活动永远不会为空。我的应用程序只有几个活动和许多片段,所以我无法真正看到这种方法今天如何运作良好。我过去在使用异步任务等交换片段时遇到了问题,并希望确保我不会再遇到与上下文无关的问题。
因此,如果我在异步任务完成后检查片段中的isAdded()
,那么getActivity()
是否保证为非空?我应该每次调用executePendingTransactions()just beforehand来确定吗?这一切都有点过分吗?
感谢您的任何反馈!
答案 0 :(得分:1)
来自doc:
public final boolean isAdded ()
Return true if the fragment is currently added to its activity.
所以活动不能为空。
编辑:
要实现长时间运行的任务,我建议您使用 IntentService (如果任务执行复杂的本地操作,否则AsyncTask就可以了),将数据保存在 DB 中(或者以其他形式,例如在SharedPreferences中,如果它是一小部分信息)并使用 LocalBroadcast 传播逻辑。您还可以管理对片段的 onCreate()回调的检查,这样如果在任务过期时它被分离,它可以检索持久化的数据并正确管理它们;之后,您可以刷新先前存储的数据。