我正在嘗試更新我的應用程序以手動處理配置更改(尤其是屏幕轉向)。Android:關於在線程運行時手動處理配置更改的問題
我對線程執行期間發生更改時發生的情況有一些疑問。
我創建了一個抽象類,我調用ThreadTask,它使用主線程的Looper的線程和處理程序向主線程發送更新。這是我的AsyncTask實現,但帶有線程,我更喜歡使用AsyncTask,因爲我對它有更多的控制。
它也有兩種方法來註冊一個觀察者上述事件,它使用這個接口:
public interface TaskObserver {
void pre_execute();
void on_progress(ProgressData progress);
void finished(Object result);
void cancelled(Object result);
}
的子類必須實現的抽象成員是:
abstract Object do_in_background();
和一些具體的成員是:
synchronized void add_observer(TaskObserver observer){
_observers.add(observer);
}
synchronized void remove_observer(TaskObserver observer){
_observers.remove(observer);
}
synchronized void post_execute(Object result) {
int observers = _observers.size();
for (int idx = 0; idx < observers; idx++) {
_observers.get(idx).finished(result);
}
}
///plus all the other methods of the interface
所以當我實現一個具體的類時它會這樣mething這樣的:
public class MyThreadTask extends ThreadTask{
@Override
Object do_in_background() {
progress.primary_max = 5;
for (int cur = 0 ; cur < 5 ; cur++) {
progress.primary = cur;
publish();
Thread.Sleep(3000);
}
}
}
和我更新調用此像這樣的活動:
static final string TAG ="my_main_activity";
MyDataFragment _data; //this is a datafragment, a fragment with retaininstancestate , and a public `MyThreadTask task` variable
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (_data == null) {
_data = (MyDataFragment)getFragmentManager().findFragmentByTag(TAG + "_data");
if (_data == null) {
_data = new MyDataFragment();
getFragmentManager().beginTransaction().add(_data, TAG + "_data").commit();
}
}
if (_data.task != null) {
_data.task.register(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (_data.task != null) {
_data.task.remove(this);
}
}
這可以確保我總是有正確的線程
參考。當我想開始任務我這樣做:
button.setOnClickListener((v) -> {
if (_data.task != null) return; //to make sure only one thread starts at a time
_data.task = new MyThreadTask();
_data.task.register(this);
_data.task.start(); //this is not thread's start, it is mine, it does other things too
})
當線程完成它調用void f inished(對象結果),我處理,像這樣:
void finished(Object result) {
try {
//get result;
} finally {
_data.task.remove(this);
_data.task = null;
}
}
這裏是我的問題:
一)被宣告我的觀測方法爲synchronized有必要嗎?我只是爲了確保,但是當活動被銷燬並重新創建時,它是否發生在同一個線程上?有沒有機會例如在onDestroy期間觀察者被移除時progress_update可能發生?
b)如果線程在配置更改期間完成並調用post_execute(這很重要)會發生什麼?更新會丟失嗎?
c)如果確實更新因爲目前沒有觀察者而丟失,那麼在我的實現或其他方法中,是否有辦法處理上述問題?
預先感謝任何幫助,您可以提供
我在保留片段收留了它,MyDataFragment _data是一個保留的片段。感謝isChangingConfigurations方法,它可能會有所幫助。另外感謝有關AsyncTask的信息,我會看看AsyncTask的代碼,看看我是否也可以在我的代碼中複製該行爲 – Cruces
嗯,我檢查了AsyncTask的代碼,並且我沒有看到任何特殊的預防措施在配置更改期間運行postexecute。它似乎使用一個簡單的處理程序發佈完成數據到任務,然後調用onpostexecute,也許我錯過了什麼? – Cruces
@Cruces它不在'AsyncTask'的代碼中。這是框架將配置更改的所有步驟發佈到整個主線程的結果。 –