[英]Android onStart() event is called when the screen is turned off
I got an Android app which needs to load some data from a website and then display it. 我有一个Android应用程序,需要从网站加载一些数据然后显示它。 For that purpose, the user gets shown a loading bar, in a background thread loads the website and then it switches back to the main thread (with a
Handler
) and displays the information. 为此,向用户显示一个加载栏,在后台线程中加载网站,然后切换回主线程(使用
Handler
)并显示信息。 So far so good, no problem here. 到目前为止一切顺利,这里没有问题。 But if the user turns off the phone while the information are being loaded and doesn't return when they are displayed, the app crashes.
但是,如果用户在加载信息时关闭了手机,却在显示信息时没有返回,则应用程序将崩溃。
So I need to interrupt the process when the user turns off his phone and retry it when he turns it on again. 因此,我需要在用户关闭手机时中断该过程,并在再次打开手机时重试。 This shouldn't be a problem, as explained here , there are a lot of events to do such things.
正如这里所解释的 ,这不应该是一个问题,有很多事件可以做到这一点。
But my debug messages showed, that the onStart()
-Event (which would be perfect for my problem) is somehow called, when the user's phone is still turned off! 但是我的调试消息显示,当用户的手机仍处于关闭状态时,
onStart()
Event(对我的问题而言非常理想)被调用了! This causes bugs. 这会导致错误。 Is there any way to avoid that?
有什么办法可以避免这种情况?
Edit: Here's my code (trimmed, of course) 编辑:这是我的代码(当然,已修剪)
(MainActivity.java) (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) (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;
}
A part of StatusPage.java: 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);
[...]
}
The LogCat: 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)
I would expect onStart
and onStop()
to be also called, when the screen is turned off. 我希望在屏幕关闭时也可以调用
onStart
和onStop()
。 The docs say, they're called, when the Activity isn't visible anymore/visible again. 文档说,当“活动”不再可见/再次可见时,它们被称为。 And because when the screen is turned off, nothing is visible (or the LockScreen at least) I expect them to be called.
而且由于关闭屏幕后,看不到任何内容(或者至少是LockScreen),所以我希望它们被调用。 They are, but
onStart()
is called in the wrong place. 他们是,但是
onStart()
在错误的地方被调用。
Why is onStart()
perfect for your problem? 为什么
onStart()
适合您的问题? Why not onCreate()
? 为什么不
onCreate()
呢?
One way to overcome this issue is to have a global boolean value set to true in the 克服此问题的一种方法是将全局布尔值设置为true
onRestart()
method. 方法。 And in the
而在
onStart()
method check if that boolean is true, if it is, do not go on with the process that causes bugs, otherwise, go on. 方法检查布尔值是否为真,如果是,则不要继续执行导致错误的过程,否则继续。 After that, in the
之后,在
onStart()
method set that boolean to false. 方法将布尔值设置为false。
May be you can do it another way. 也许您可以用另一种方式来做。 Register broadcast receiver with Intent.ACTION_SCREEN_OFF, Intent.ACTION_SCREEN_ON
使用Intent.ACTION_SCREEN_OFF,Intent.ACTION_SCREEN_ON注册广播接收器
OK, I've figured it out. 好,我知道了。 In the
onStart()
-Method I simply check if the screen is turned on or not. 在
onStart()
方法中,我只是检查屏幕是否打开。 If it's not, the call is not handled. 如果不是,则不处理该呼叫。 That's maybe not a solution, but at last a workaround.
那也许不是解决方案,但最后是一种解决方法。 This is what my code now looks like:
这是我的代码现在的样子:
@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();
}
}
When a phone is turned off,is can be waked up by notifications or some other system services,may make your activity be active. 当手机关闭时,可以通过通知或其他系统服务唤醒,可能会使您的活动处于活动状态。
onStart() : Called when the activity is becoming visible to the user. onStart():在活动对用户可见时调用。
onResume(): Called when the activity will start interacting with the user. onResume():当活动将开始与用户进行交互时调用。
You may change to execute your code in onResume(). 您可以更改以在onResume()中执行代码。
If this is too late for you,you can add a judgement if phone is turned off by PowerManager. 如果这对您来说太迟了,您可以添加一个判断,以判断PowerManager是否关闭了电话。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.