0

我创建了具有登录功能的简单应用程序。我创建了单独的任务,用于登录到名为的服务器LoginTask和一个名为的侦听器类LoginListener

public interface LoginListener {
    public void onLoginComplete();
    public void onLoginFailure(String msg);
}

public class LoginTask extends AsyncTask<String, Void, Boolean>{
    private final LoginListener listener;
    private final Context c;
    private String msg;

    public LoginTask(final Context c, final LoginListener listener) {
        this.c = c;
        this.listener = listener;
    }

    @Override
    protected Boolean doInBackground(String... args) {
        // loging in to server
        //return true if success
    }

    @Override
    protected void onPostExecute(Boolean status) {
        if(!status){
            if(listener != null) listener.onLoginFailure(msg);
                return;
        }       

        // the problem is here, listener is null, because activity/fragment destroyed
        if(listener != null) listener.onLoginComplete();
    }
}

LoginTaskLoginFragment. LoginFragment工具LoginListener。_

public class LoginFragment extends Fragment implements LoginListener{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.frg_login, container, false);
    }

    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        doInitView();
    };

    private void doInitView(){
        Button loginButton = (Button) getActivity().findViewById(R.id.login_btn);
        Button regButton = (Button) getActivity().findViewById(R.id.toreg_btn);

        ButtonListener listener = new ButtonListener();
        loginButton.setOnClickListener(listener);
        regButton.setOnClickListener(listener);
    }

    private void doLogin(){
        Activity activity = getActivity();
        EditText emailText = (EditText)activity.findViewById(R.id.login_email);
        EditText pwdText = (EditText)activity.findViewById(R.id.login_pwd);

        String email = emailText.getText().toString().trim();
        String pwd = pwdText.getText().toString().trim();

        if(StringUtil.isAnyNull(email, pwd)){
            Popup.showMsg(getActivity(), "Silahkan lengkapi data", Popup.SHORT);
            return;
        }

        savedEmail = email;
        savedPwd = pwd;
        String url = getActivity().getResources().getString(R.string.url_login);
        Popup.showLoading(getActivity(), "Login", "Please wait...");
        LoginTask task = new LoginTask(getActivity(), this);
        task.execute(url, email, pwd);
    }

    private final class ButtonListener implements OnClickListener{

        @Override
        public void onClick(View v) {
            switch(v.getId()){
            case R.id.login_btn:
                doLogin();
                break;
            case R.id.toreg_btn:
                doToRegister();
                break;
            case R.id.demo_btn:
                doDemo();
                break;
            }
        }        
    }

    @Override
    public void onLoginComplete() {
        // getActivity() is null
        ((MainActivity)getActivity()).gotoMain();
    }

    @Override
    public void onLoginFailure(String msg) {

    }    
}

由于登录任务需要时间,有时设备灯会在任务完成之前关闭,因此活动被破坏。这导致任务调用监听器(片段)失败。如何解决这个问题呢?

谢谢

4

4 回答 4

3

AsyncTask应该用于需要更长时间并将结果返回到当前活动的任务。但是,它不适用于真正长时间运行的任务,也不适用于即使活动已被破坏也想要评估其结果的情况。

你可以考虑在Service这里使用。在任何情况下,您都不应该再进行更新,onPostExecute()因为活动上下文可能会消失(请参阅Doctoror Drive的帖子)。

有了该服务,您可以向系统发送一个Intent或一个Broadcast事件。然后在该意图活动/广播接收器中进行进一步处理。

于 2013-03-17T14:03:00.740 回答
1

您可以在 LoginActivity 的 onDestroy() 中取消异步任务。

覆盖异步任务的 onCancelled()。当活动被销毁时,将调用 onCancelled() 而不是 onPostExecute()

在这里您可以避免对 LoginActivity 的回调。

于 2013-03-17T13:55:38.387 回答
1

您应该使用ServiceIntentService。因为AsyncTask不记录任何变量或上下文Activity。当您完成登录任务启动PendingIntentstartActivity(intent). 这可能是 Android 的最佳实践。这样你永远不会得到异常。

于 2013-03-17T14:08:52.200 回答
0

在 onLoginComplete 和 onLoginFailure 检查片段是否仍然附加到活动。如果没有,什么也不做。

@Override
public void onLoginComplete() {

    if (isAdded() && !isRemoving() && !isDetached()) {
        ((MainActivity)getActivity()).gotoMain();
    }
}
于 2013-03-17T13:51:43.453 回答