Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android-多个活动重启时的并发问题_Java_Android_Concurrency_Activity Lifecycle - Fatal编程技术网

Java Android-多个活动重启时的并发问题

Java Android-多个活动重启时的并发问题,java,android,concurrency,activity-lifecycle,Java,Android,Concurrency,Activity Lifecycle,在模拟器(ADT v17.0.0)或设备(原始Droid)上进行方向更改时,我注意到该活动有时会经历多个创建-销毁周期。我发现它提到了这个问题,但没有提供解决方案 我的应用程序(API 8)目前在onPause中“最后一次机会”保存用户数据,并在onCreate/onStart中检索该数据,这对于一次重新启动很好,但如果循环连续出现,则会出现并发问题。特别是,如果在保存完成之前开始加载,“最后一次机会”数据将丢失 我确实读过《更快的屏幕方向改变Android开发者》一文,其中提到通过onReta

在模拟器(ADT v17.0.0)或设备(原始Droid)上进行方向更改时,我注意到该活动有时会经历多个创建-销毁周期。我发现它提到了这个问题,但没有提供解决方案

我的应用程序(API 8)目前在onPause中“最后一次机会”保存用户数据,并在onCreate/onStart中检索该数据,这对于一次重新启动很好,但如果循环连续出现,则会出现并发问题。特别是,如果在保存完成之前开始加载,“最后一次机会”数据将丢失

我确实读过《更快的屏幕方向改变Android开发者》一文,其中提到通过onRetainonConfiguration实例/GetLastNonConConfiguration实例传输对象。我尝试使用onRetain/getLast。。。类似于一个标志来告诉活动是否“重新启动”,这是有效的,但我仍然有一个主要问题,即不知道任何现有的保存/加载操作是否/何时完成

并发性和线程管理不是我的强项,因此我正在寻找一种解决方案,它可以在任意数量的背对背重新启动中至少执行一次保存和加载,而不会出现内存泄漏。由于快速创建-销毁循环可能是由于非方向性原因而发生的,因此仅涉及破坏/处理方向性更改的想法并不是我真正想要的

摘录一些循环,你可以看到在从风景画到肖像画的过程中,活动被创建和破坏了两次。下面是我现在得到的一个摘录:

onPause() {
    file_manager.saveTemporaryPattern(); // writes to OutputStream on UI thread
}

onStart() {
    findViewById (R.id.main_screen).post (new Runnable() {
        file_manager.loadTemporaryPattern(); // reads from InputStream on UI thread
    });

    if (getLastNonConfigurationInstance() != null) {
        // DO SOMETHING HERE?
    }
}

onRetainNonConfigurationInstance() {
    return dummy_object;
}

通过向链接到应用程序上下文(而不是活动上下文)的处理程序线程发送加载/保存调用来解决并发性问题。必须在调用中设置Load vs Save token以检查保存->加载->保存模式,避免在横向->纵向方向更改中获得不完整活动生命周期的奇怪行为

它在开发和测试设备上工作,并且不会泄漏活动上下文,因此我们将了解它在野外的工作情况

在YourApp中扩展应用程序:

private Handler fileAccessThread = null;

public void onCreate() {
    super.onCreate();

    if (fileAccessThread == null) {
        fileAccessThread = new Handler();
        token = 0;
    }
}

public void postCallbackFileAccess (int _token, Runnable _callback) {
    switch (_token) {
    case TOKEN_SAVE:
        // Save must follow load, not another save
        if (token == TOKEN_SAVE) { return; }
        token = _token;
        break;

    case TOKEN_LOAD:
//      Have to allow load->load, otherwise data gets lost/deleted
//      if (token == TOKEN_LOAD) { return; }
        token = _token;
        break;
    }

    fileAccessThread.post (_callback);
}
protected void onStart() {
    super.onStart();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_LOAD, new Runnable() {
            @Override
            public void run() {
                file_manager.load();
            }
    });
}

protected void onPause() {
    super.onPause();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_SAVE, new Runnable() {
            @Override
            public void run() {
                file_manager.save();
            }
    });
}
在您的活动中:

private Handler fileAccessThread = null;

public void onCreate() {
    super.onCreate();

    if (fileAccessThread == null) {
        fileAccessThread = new Handler();
        token = 0;
    }
}

public void postCallbackFileAccess (int _token, Runnable _callback) {
    switch (_token) {
    case TOKEN_SAVE:
        // Save must follow load, not another save
        if (token == TOKEN_SAVE) { return; }
        token = _token;
        break;

    case TOKEN_LOAD:
//      Have to allow load->load, otherwise data gets lost/deleted
//      if (token == TOKEN_LOAD) { return; }
        token = _token;
        break;
    }

    fileAccessThread.post (_callback);
}
protected void onStart() {
    super.onStart();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_LOAD, new Runnable() {
            @Override
            public void run() {
                file_manager.load();
            }
    });
}

protected void onPause() {
    super.onPause();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_SAVE, new Runnable() {
            @Override
            public void run() {
                file_manager.save();
            }
    });
}

通过向链接到应用程序上下文(而不是活动上下文)的处理程序线程发送加载/保存调用来解决并发性问题。必须在调用中设置Load vs Save token以检查保存->加载->保存模式,避免在横向->纵向方向更改中获得不完整活动生命周期的奇怪行为

它在开发和测试设备上工作,并且不会泄漏活动上下文,因此我们将了解它在野外的工作情况

在YourApp中扩展应用程序:

private Handler fileAccessThread = null;

public void onCreate() {
    super.onCreate();

    if (fileAccessThread == null) {
        fileAccessThread = new Handler();
        token = 0;
    }
}

public void postCallbackFileAccess (int _token, Runnable _callback) {
    switch (_token) {
    case TOKEN_SAVE:
        // Save must follow load, not another save
        if (token == TOKEN_SAVE) { return; }
        token = _token;
        break;

    case TOKEN_LOAD:
//      Have to allow load->load, otherwise data gets lost/deleted
//      if (token == TOKEN_LOAD) { return; }
        token = _token;
        break;
    }

    fileAccessThread.post (_callback);
}
protected void onStart() {
    super.onStart();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_LOAD, new Runnable() {
            @Override
            public void run() {
                file_manager.load();
            }
    });
}

protected void onPause() {
    super.onPause();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_SAVE, new Runnable() {
            @Override
            public void run() {
                file_manager.save();
            }
    });
}
在您的活动中:

private Handler fileAccessThread = null;

public void onCreate() {
    super.onCreate();

    if (fileAccessThread == null) {
        fileAccessThread = new Handler();
        token = 0;
    }
}

public void postCallbackFileAccess (int _token, Runnable _callback) {
    switch (_token) {
    case TOKEN_SAVE:
        // Save must follow load, not another save
        if (token == TOKEN_SAVE) { return; }
        token = _token;
        break;

    case TOKEN_LOAD:
//      Have to allow load->load, otherwise data gets lost/deleted
//      if (token == TOKEN_LOAD) { return; }
        token = _token;
        break;
    }

    fileAccessThread.post (_callback);
}
protected void onStart() {
    super.onStart();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_LOAD, new Runnable() {
            @Override
            public void run() {
                file_manager.load();
            }
    });
}

protected void onPause() {
    super.onPause();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_SAVE, new Runnable() {
            @Override
            public void run() {
                file_manager.save();
            }
    });
}