首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OnSaveInstanceState/ RestCalls

OnSaveInstanceState/ RestCalls
EN

Stack Overflow用户
提问于 2016-08-11 14:15:37
回答 1查看 94关注 0票数 2

我对Android开发还比较陌生,我有一个关于onSaveInstanceState()的问题。我目前正在为一个应用程序进行登录活动。为了检查用户是否可以登录到他们的帐户,我对服务器执行rest调用,并根据响应代码查看是否应该授予用户访问权限。我问题的根源在于,我试图避免将活动的上下文传递给rest调用类。为此,我在登录活动中创建了一个布尔字段,表示rest调用是否成功,更新布尔值的可运行性表示我传递给rest-call类。我知道这与AsyncTask的想法背道而驰,但我无法找到任何替代方法,只需设置一个对话框让用户在此过程中等待。下面是我的问题。

1)如果在savedInstanceState方法中使用onCreate (),如何首次实例化此布尔字段,除非检查对象布尔值为空?我的意思是,在活动因任何原因而被破坏后(例如,改变方向等)我将使用存储在overriden onSaveInstanceState方法中的布尔值;但是,当第一次创建它时,它没有对布尔值的引用,因此必须创建一个布尔值。

( 2)这个可运行的甚至有帮助吗?我这样做是为了不需要传递上下文,但是如果要在RestCall(AsyncTask)完成之前删除活动,那么传递上下文还是影响活动字段的可运行性真的很重要吗?我越多地思考这个问题,我就越相信它不会产生太大的影响,因为它仍然会导致它指向一个不存在的对象。我试图避免使用单例设计,因为我认为它不是最优的,但由于与AsyncTask的潜在时间滞后,我开始认为它可能是不可避免的。

我知道onSaveInstanceState()是StackOverflow上提到的一个话题,但是我找不到这些问题的答案。我很抱歉,如果已经有一条线索,但任何帮助或指导将是非常感谢的!谢谢!

登录活动的设置:

代码语言:javascript
复制
public class LoginActivity extends Activity implements View.OnClickListener {

private EditText username_et;
private EditText password_et;
private Button login_b;
private boolean login_success = true;
private Runnable run;


/**
 * Instances created when app starts
 */

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view_login);
//  login_success = false;
    login_success = savedInstanceState.getBoolean("login_success");
    username_et = (EditText) findViewById(R.id.username_text);
    username_et.setOnClickListener(LoginActivity.this);
    password_et = (EditText) findViewById(R.id.password_text);
    password_et.setOnClickListener(LoginActivity.this);
    login_b = (Button) findViewById(R.id.login_button);
    login_b.setOnClickListener(LoginActivity.this);
    run = new Runnable() {
        @Override
        public void run() {
            login_success = true;
        }
    };
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState){
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putBoolean("login_success", login_success);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-11 14:45:58

祝贺你。你刚刚发现了Android的肮脏小秘密。

AsyncTask有一个固有的设计缺陷。由于您提到的问题,它不能很好地处理后台任务执行过程中发生的配置更改。它需要保存对活动的引用,但在后台任务完成时,不能保证引用仍然有效。

以下是克服这个问题的两种方法:

  1. 我建议您参阅亚历克斯·洛克伍德出色的博客文章,介绍如何使用隐藏的片段和setRetainInstance(true)来跨越活动、破坏和娱乐。这是一个比下一个解决方案更复杂的解决方案,但是这个解决方案的优点是您仍然可以报告回调的进度。如果您打算在您的publishProgress()中调用AsyncTask,那么应该使用这一方法。
  2. 使用Loader。加载器是围绕后台数据库数据检索而设计的,但事实上它们也可以用于处理后台的远程服务器访问。我在大多数远程服务器任务中使用Loader。 下面是一个例子: 公共静态类ResetPasswordLoader扩展AsyncTaskLoader> {私有静态最终字符串标记= "ResetPasswordLoader ";私有字符串mEmail;公共ResetPasswordLoader(上下文,字符串电子邮件){超级(上下文);mEmail = email;//设置内容更改标志onContentChanged();@覆盖受保护的无效onStartLoading() { //仅在设置了// takeContentChanged()设置了内容更改标志时才启动加载,如果(takeContentChanged()) { forceLoad();}@forceLoad();}@覆盖公共Pair loadInBackground() { CharSequence结果= null;异常exc = null;尝试{ result = Service.getInstance().resetPassword(mEmail);} catch (RemoteServiceException e) { exc = e;Log.e(标记,"loadInBackground(),email =“+ mEmail,e);}返回新Pair<>(结果,exc);}} 此外,在我的onLoadFinished()覆盖中,我确保在加载程序的id上调用loaderManager.destroyLoader()。 同样,的博客也有一些关于加载器的优秀文章。

对于UI,我经常做的事情是在调用loaderManager.initLoader()时在UI上设置一个不确定的进度条。我还设置了像mProgressShown这样的布尔值。这个布尔值保存在onSaveInstanceState中,所以当再次创建活动/片段时,我恢复布尔值,该值告诉我立即显示进度条。稍后将调用onLoadFinished,我清除mProgressShown并隐藏进度条。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38898883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档