2016-03-20 45 views
0

我有一个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) 

我希望onStartonStop()被又称,当屏幕被关闭。文档说,他们被称为,当活动不再可见/再次可见时。而且因为当屏幕关闭时,没有任何东西可见(或至少是LockScreen),我期望它们被调用。他们是,但onStart()被调用在错误的地方。

+0

onStart没有按照屏幕打开和关闭来定义。它是根据用户可见的活动来定义的。你真的需要在屏幕上开启/关闭,还是需要触发可视性?他们是不同的东西。 –

+0

@Doug Stevenson在某种程度上,两者都有。加载数据后,该进程尝试显示它。如果活动不可见或屏幕已关闭,则这不起作用 – Namnodorel

+0

实际上,更新停止且不可见(但尚未销毁)的活动的视图层次结构没有问题。直到下一次onStart才能看到更改。 –

回答

0

为什么onStart()适合您的问题?为什么不是onCreate()?为了解决这个问题

的方法之一是必须在

onRestart() 

方法设置为true,一个全球性的布尔值。而在

onStart() 

方法检查如果布尔值为true,如果是,不引起错误的过程中去,否则,继续。之后,在

onStart() 

方法将布尔值设置为false。

+0

当Activtiy开始时,onCreate()被调用;我需要一些在屏幕关闭/打开时调用的东西;)我尝试了类似的东西(用onStop()而不是onRestart());我在onStop()中设置布尔值为false(如果一个操作正在运行,它会在发现bug之前停止),并将onStart()设置为true(另外我正在重新启动加载过程,因为不应该存在一个空白屏幕)。但是因为onStart()在屏幕关闭时被调用,所以如果一个正在运行的进程出现了这个bug,它就不会停下来。我想这也是解决方案中存在的问题。 – Namnodorel

+0

当屏幕处于关闭状态时,onStart不会被调用,它会在打开并调用此Activity时被调用。你能分享一下bug或logcat来看看错误吗? – mmcoder10

+0

刚刚添加的代码和logcat – Namnodorel

0

可能是你可以做到另一种方式。用Intent.ACTION_SCREEN_OFF注册广播接收机,Intent.ACTION_SCREEN_ON

0

好的,我已经想通了。在onStart() - 方法我只是检查屏幕是否打开。如果不是,则不处理该呼叫。这可能不是一个解决方案,但最终是一种解决方法。这是我的代码现在看起来像:

@Override 
public void onStart(){ 
    super.onStart(); 

    if(isScreenOn()) { 
     PageManager.mayContinue(true); 

     if(PageManager.getCurrentPage() == null) { 
      PageManager.loadPage(new StatusPage()); 
     }else{ 
      PageManager.loadPage(PageManager.getCurrentPage()); 
     } 
    } 

} 


@Override 
public void onStop(){ 
    super.onStop(); 

    PageManager.mayContinue(false); 
} 

    public boolean isScreenOn(){ 
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 

    if (Build.VERSION.SDK_INT < 21) { 
     return pm.isScreenOn(); 
    }else{ 
     return pm.isInteractive(); 
    } 
} 
+0

顺便说一句,它并没有完全解决Bug,因为onStart()有时也被称为手机尚未解锁时调用。但这不是问题所在。 – Namnodorel

0

当手机关机时,可以通过通知或其他一些系统服务醒了,可能使你的活动是活动的。

onStart():当活动对用户变得可见时调用。

onResume():当活动开始与用户交互时调用。

您可以更改为在onResume()中执行您的代码。

如果这对您来说太迟了,您可以添加一个判断,如果电话被PowerManager关闭。

相关问题