我有一個Android應用程序需要從網站加載一些數據,然後顯示它。爲此,用戶會看到一個加載欄,在後臺線程加載網站,然後切換回主線程(帶有Handler
)並顯示信息。到目前爲止這麼好,這裏沒有問題。但是,如果用戶在加載信息時關閉手機,並在顯示時未返回,則應用程序會崩潰。當屏幕關閉時,會調用Android onStart()事件
因此,當用戶關閉手機並重新打開手機時,需要中斷該過程。這應該不是問題,有很多事情要做這樣的事情。
但我的調試信息顯示onStart()
-Event(這對我的問題來說是完美的)以某種方式稱爲,當用戶的手機仍然關閉時!這會導致錯誤。有什麼辦法可以避免這種情況?
編輯: 這裏是我的代碼(修剪,當然)
(MainActivity.java)
private static MainActivity activity;
//Handler to run code from other threads in the main thread (needed to modify the GUI)
private static Handler handler;
private static ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
activity = this;
handler = new Handler();
[...]
}
@Override
public void onStart(){
super.onStart();
Log.e("s", "start");
PageManager.mayContinue(true);
if(PageManager.getCurrentPage() == null) {
PageManager.loadPage(new StatusPage());
}else{
PageManager.loadPage(PageManager.getCurrentPage());
}
}
@Override
public void onStop(){
super.onStop();
Log.e("s", "Stop");
PageManager.mayContinue(false);
}
public static MainActivity getActivity(){
return activity;
}
public static void runOnMainThread(Runnable r){
handler.post(r);
}
(PageManager.java)
private static Boolean isPageLoading = false;
private static Page currentPage;
private static boolean mayContinue;
public static void loadPage(final Page page){
if(isPageLoading){
return;
}
if(currentPage != null) {
boolean allowedToLoadDifferentPage = currentPage.onPageLeft();
if (!allowedToLoadDifferentPage) {
return;
}
}
isPageLoading = true;
FragmentManager fragmentManager = MainActivity.getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
DisplayFragment fragment = new DisplayFragment();
fragment.setPage(page);
fragmentTransaction.replace(R.id.display_fragment, fragment);
fragmentTransaction.commit();
MainActivity.getProgressBar().setVisibility(View.VISIBLE);
Runnable r = new Runnable(){
@Override
public void run() {
//Load the required data
page.loadPage();
isPageLoading = false;
if(!mayContinue){
MainActivity.runOnMainThread(new Runnable() {
@Override
public void run() {
MainActivity.getProgressBar().setVisibility(View.INVISIBLE);
}
});
Log.e("PageManager", "Loading process got blocked!");
return;
}
currentPage = page;
MainActivity.runOnMainThread(new Runnable() {
@Override
public void run() {
MainActivity.getProgressBar().setVisibility(View.INVISIBLE);
//Display the loaded data
page.setViewValues();
}
});
}
};
new Thread(r).start();
}
public static Page getCurrentPage(){
return currentPage;
}
public static void mayContinue(boolean value) {
mayContinue = value;
}
StatusPage的一部分.java:
@Override
public void setViewValues() {
RecyclerView rv = (RecyclerView)MainActivity.getActivity().findViewById(R.id.insert_values);
LinearLayoutManager llm = new LinearLayoutManager(MainActivity.getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
rv.setLayoutManager(llm);
RecyclerViewAdapter adapter = new RecyclerViewAdapter();
rv.setAdapter(adapter);
[...]
}
的logcat的:
03-21 07:50:38.109 6121-6121/de.namnodorel.app E/s: start //The Activity got launched
03-21 07:50:38.261 6121-6121/de.namnodorel.app E/RecyclerView: No adapter attached; skipping layout
03-21 07:50:38.342 6121-6121/de.namnodorel.app E/RecyclerView: No adapter attached; skipping layout
//I turn the phone off
03-21 07:50:39.541 6121-6121/de.namnodorel.app E/s: Stop
//??? (I didn't turn it on)
03-21 07:50:40.326 6121-6121/de.namnodorel.app E/s: start
//The app crashes because the findViewById() returned null (which means there is nothing with that ID on the current screen)
03-21 07:50:41.337 6121-6121/de.namnodorel.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.namnodorel.app, PID: 6121
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
at
de.namnodorel.app.game.status.StatusPage.setViewValues(StatusPage.java:47)
at de.namnodorel.app.game.PageManager$1$2.run(PageManager.java:75)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
我希望onStart
和onStop()
被又稱,當屏幕被關閉。文檔說,他們被稱爲,當活動不再可見/再次可見時。而且因爲當屏幕關閉時,沒有任何東西可見(或至少是LockScreen),我期望它們被調用。他們是,但onStart()
被調用在錯誤的地方。
onStart沒有按照屏幕打開和關閉來定義。它是根據用戶可見的活動來定義的。你真的需要在屏幕上開啓/關閉,還是需要觸發可視性?他們是不同的東西。 –
@Doug Stevenson在某種程度上,兩者都有。加載數據後,該進程嘗試顯示它。如果活動不可見或屏幕已關閉,則這不起作用 – Namnodorel
實際上,更新停止且不可見(但尚未銷燬)的活動的視圖層次結構沒有問題。直到下一次onStart才能看到更改。 –