簡體   English   中英

為什么我的 onResume 被調用兩次?

[英]Why is my onResume being called twice?

基本上,這就是我正在做的

1)設置AlarmManager執行BroadcastReceiver(BCR)

Intent intent = new Intent(m_Context, BCR.class);  
intent.putExtras(extras);  
PendingIntent pendingIntent = PendingIntent.getBroadcast(m_Context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, StartTime, pendingIntent)  

2) 從 BCR 啟動 MyActivity

@Override  
public void onReceive(Context context, Intent intent) {  
    Intent newIntent = new Intent(context, MyActivity.class);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);  
    context.startActivity(newIntent);  
}

3) 如果 MyActivity 沒有打開,讓它打開屏幕

@Override  
public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState); 
    getWindow().addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
    getWindow().addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    getWindow().addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);
    setContentView(R.layout.myactivity);  
} 

@Overide  
protected void onNewIntent(Intent intent) {  
    super.onNewIntent(intent);  
}  

出於某種原因,我注意到當 MyActivity 打開時,它的流程是這樣的:

onCreate/onNewIntent -> onResume -> onPause -> onResume

我不確定為什么它會立即執行 onPause。 我注意到這僅在標志打開屏蔽時才會發生。 有誰知道為什么會這樣? 有什么辦法可以防止這種行為嗎?

以防萬一其他人遇到這種情況,我似乎只有在我通過 XML 布局在活動內膨脹片段時才會注意到這種行為。 我不知道這種行為是否也發生在 Fragments 的兼容庫版本中(我使用的是 android.app.Fragment)

似乎活動會在調用Fragment#onResume到任何添加的 Fragment 之前調用Activity#onResume一次,然后再次調用Activity#onResume

  1. 活動:onCreate
  2. 片段:附加
  3. 活動:onAttachFragments
  4. 片段:onCreate
  5. 活動:onStart
  6. 活動:onResume
  7. 片段:onResume
  8. 活動:onResume

如果您每次嘗試請求權限都會導致此類問題,請檢查您是否已經授予它們

requestPermissions可能導致它:

onCreate
onStart
onResume
onPause
onResume

使用此方法ContextCompat.checkSelfPermission(context,permission)在請求之前檢查是否授予權限

此方法返回int ,您可以使用PackageManager.PERMISSION_GRANTED常量檢查它

如果您有ES File Explorer強制停止它。 不知何故,它們會中斷您的應用程序的生命周期(評論建議某種覆蓋)

我的兩次onResume問題是因為在創建活動后以某種方式調用了onPause .. 有什么東西打斷了我的應用程序。

只會在安裝后第一次打開或從工作室構建發生。

我從另一篇文章中得到了線索,發現這是因為 ES 文件資源管理器。 為什么 onResume() 似乎被調用了兩次?

一旦我強制停止 ES File Explorer ,這種打嗝行為就不再發生......在嘗試了許多其他建議的解決方案后知道這令人沮喪。 因此,請注意任何其他像這樣的中斷應用程序。

我研究了一段時間,因為在互聯網上沒有提到這種奇怪的行為。 我沒有如何克服這種陰暗面行為的解決方案,但我找到了一個確切的場景,當它確實發生時。

onPause-onResume-onPause-onResume每次都會發生,當應用程序在安裝后第一次啟動時。 您可以通過對代碼進行任何更改並從您的 IDE 重新運行(包括重新編譯)應用程序來簡單地調用此行為。

無論您是否使用 AppCompat 庫。 我已經測試了這兩種情況,行為仍在繼續。

注意:在 Android Marshmallow 上測試。

我從這個線程中借用了關於片段和活動生命周期的代碼,這里是(只需復制、粘貼、在清單中聲明活動並運行 Forest run):

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class TestActivity extends Activity {

    private static final String TAG = "ACTIVITY";

    public TestActivity() {
        super();
        Log.d(TAG, this + ": this()");
    }

    protected void finalize() throws Throwable {
        super.finalize();
        Log.d(TAG, this + ": finalize()");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this + ": onCreate()");


        TextView tv = new TextView(this);
        tv.setText("Hello world");
        setContentView(tv);

        if (getFragmentManager().findFragmentByTag("test_fragment") == null) {
            Log.d(TAG, this + ": Existing fragment not found.");
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(new TestFragment(), "test_fragment").commit();
        } else {
            Log.d(TAG, this + ": Existing fragment found.");
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, this + ": onStart()");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, this + ": onResume()");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, this + ": onPause()");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, this + ": onStop()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, this + ": onDestroy()");
    }


    public static class TestFragment extends Fragment {

        private static final String TAG = "FRAGMENT";

        public TestFragment() {
            super();
            Log.d(TAG, this + ": this() " + this);
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, this + ": onCreate()");
        }


        @Override
        public void onAttach(final Context context) {
            super.onAttach(context);
            Log.d(TAG, this + ": onAttach(" + context + ")");
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, this + ": onActivityCreated()");
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d(TAG, this + ": onCreateView()");
            return null;
        }

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            Log.d(TAG, this + ": onViewCreated()");
        }

        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d(TAG, this + ": onDestroyView()");
        }

        @Override
        public void onDetach() {
            super.onDetach();
            Log.d(TAG, this + ": onDetach()");
        }

        @Override
        public void onStart() {
            super.onStart();
            Log.d(TAG, this + ": onStart()");
        }

        @Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, this + ": onResume()");
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, this + ": onPause()");
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, this + ": onStop()");
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG, this + ": onDestroy()");
        }
    }

}

我不確定發生了什么,但我懷疑您的活動正在重新啟動,因為設置屏幕被系統視為配置更改。 您可以嘗試在每次調用onResume記錄配置,以查看是否發生了這種情況,如果是,則實際發生了什么變化。 然后,您可以修改清單以告訴系統您的活動將自行處理更改。

protected void onResume() [
    super.onResume();
    Configuration config = new Configuration();
    config.setToDefaults();
    Log.d("Config", config.toString());
    . . .
}

我有類似的問題。 我的情況是下一個CurrentActivity extends MainActivity CurrentFragment extends MainFragment

我像往常一樣有意打開CurrentActivity 在 onCreate CurrentAcitivity 中,我正在替換 CurrentFragment。

生命周期是: 1. onResume MainActivity 2. onResume CurrentActivity 3. onResume MainFragment 4. onResume CurrentFragment

自動調用 onPause,然后再次調用

  1. 恢復主活動
  2. 恢復當前活動
  3. onResume MainFragment
  4. onResume CurrentFragment

我決定重新測試所有內容,經過幾個小時的嘗試和播放后,我發現了根本問題。 在 MainFragment onStart 中,我每次都調用 startActivityForResult(在我的例子中是打開 Wifi 的 android 彈出窗口),在 MainFragment 上調用 onPause。 我們都知道在 onPause 之后接下來是 onResume。

所以它不是Android錯誤,它只是我的:-)

快樂的生命周期調試!

我也遇到過這個 onresume-onpause-onresume 序列(在 4.1.2 及更高版本上,但我在 2.3 上沒有遇到過這種情況)。 我的問題與喚醒鎖處理有關:我不小心忘記釋放喚醒鎖並重新獲取它導致錯誤消息“WakeLock 在仍然保持時已完成”。 此問題導致 onPause 在 onResume 后立即被調用並導致錯誤行為。

我的建議是:檢查日志中的錯誤,這些錯誤可能與此問題有關。

另一個提示:打開屏幕可能比簡單地使用窗口標志更棘手。 您可能想在此處查看此答案 - 它建議您設置一個接收器來檢查屏幕是否已打開並僅在以下時間啟動所需的活動: https : //stackoverflow.com/a/16346369/875442

似乎使用支持庫中的Activity自動保存和恢復實例。 因此,只有在savedInstanceStatenull時才執行您的工作。

我有一個類似的問題,我的問題是在 onCreate() 方法中,我正在做:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.setContentView(R.layout.friends);  <-- problem
}

我對“超級”的呼喚。 兩次觸發 onResume() 。 在我將其更改為以下后,它按預期工作:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.friends);  <-- 'super.' removed
}

希望能幫助到你。

我剛剛遇到了這個問題,似乎getWindow().addFlags()和一般調整Window屬性可能是罪魁禍首。

當我的代碼是這樣的

@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_generic_fragment_host);
    // performing fragment transaction when instance state is null...

onResume()被觸發兩次,但是當我刪除requestWindowFeature() ,它只被調用一次。

我認為你應該看看這個問題: Nexus 5 進入睡眠模式會使活動生命周期出錯你應該找到線索

基本上很多東西都可以觸發這個。 一些失去焦點的恢復過程可以做到。 一些應用程序也會導致它發生。 唯一的應對方法就是阻止雙跑。 請注意,這也會有一個錯誤的暫停。

    boolean resumeblock = false;

    @Override
    protected void onResume() {
        super.onResume();
        sceneView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                sceneView.getViewTreeObserver().removeOnPreDrawListener(this);
                if (resumeblock) return false;
                resumeblock = true;

                //Some code.

                return false;
            }
        });
    }

這是防止此類事情發生的可靠方法。 它會阻止雙重簡歷。 但是,它也會阻止兩個保留內存的簡歷。 所以,如果你只是失去了重點,它並不需要重建你的東西​​。 它也會阻止它。 這可能是一個明顯的好處,因為如果你使用簡歷來控制一些關於焦點的變化,你實際上關心是否因為焦點而需要重建那些東西。 由於預繪制監聽器只能被一個線程調用,而且必須依次調用,所以這里的代碼只會運行一次。 直到某些東西正確地破壞了整個活動並將 resumeblock 設置回 false。

正如@TWL 所說, ES 文件資源管理器對我來說是個問題! 卸載應用程序解決了這個問題。 安裝此ES 文件資源管理器后, onStart() -> onResume() -> onPause() -> onResume() .. 是問題所在。 onResume()被稱為 2'ce。

我有同樣的問題。 我的是運行時的這段代碼

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

我只是把它放在清單中

android:screenOrientation="landscape"

沒有關於兩次調用 onCreate 和 onResume 的問題。

我沒有看到這個問題的充分答案,所以我決定這樣做。

來自我的筆記:“似乎活動運行 onResume() onPause() 然后再次運行 onResume。運行的最后一個方法是 onSizeChanged()。所以一個好的做法是只有在 onSizeChanged() 方法之后才啟動線程被處決了。”

所以你可以: 記錄每個運行的方法。 確定最后運行的方法。 確保您有一個初始化 false 的布爾值,並且僅在您的最后一個方法運行后才更改為 true。 然后您可以開始所有線程操作,一旦您檢查布爾值是否為真。

-對於任何想知道的人:我使用的表面視圖具有最后執行的 onSizeChanged() 方法。

由於在MainActivityonCreate()中設置了UiMode ,我遇到了同樣的問題。 更改主題觸發了activity重新創建,並對onPause()onStart()進行了兩次調用。

onCreate方法中調用super.onCreate(savedInstanceState)之前,您是否嘗試過調用getWindow().addFlags(...)

我有一個類似的問題。 當我的onCreate看起來像這樣時, onResume被調用了兩次:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
    setContentView(R.layout.main);
    ...
}

將其更改為:

@Override
public void onCreate(Bundle savedInstanceState) {

    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ...
}

...解決了問題。

我確信這會發生在我的應用程序中,直到我意識到我已經種植了兩棵 Jake Wharton 的 Timber 樹,並且 onResume() 只是被記錄了兩次,而不是被調用了兩次。

我也遇到過這個問題,這是因為片段..您在onResume()活動中擁有的片段數將調用該次數。 為了克服我在SharedPrefrences使用標志變量

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM