安卓程式進入後台和前台的判斷

來源:互聯網
上載者:User

標籤:listener   reg   opp   get   import   cal   extend   post   使用者   

按照最簡單的思路,一個app的所有Activity全部onStop後就算進入後台,但可能使用者只是切出去看了一眼別的程式又跳了回來。從技術上來說,這種判斷沒有問題,但從使用者活躍的角度來講,使用者並沒有真正離開我們的app。還有一種情況,就是需要在程式進入前背景時候,執行一些操作,如果使用者切換的十分頻繁,操作又比較耗時可能會產生一定的效率低下和浪費。因此最簡單的解決辦法就是添加一個延時,定義一個我們app的前後台概念,即app不可見後一段時間才當做進入後台,而一旦從後台狀態顯示出來就當做進入前台。

想要判斷app進入了後台,就要關注app中每一個activity的聲明周期,比較笨的方法是整個項目中所有Activity都使用同一個基類,在這個基類中重寫聲明周期方法來進行監控。

但還有一種簡單的方式,可以監聽整個app所有Activity的生命週期變化:Application.registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)。這個方法可以註冊多個callback,不是只能註冊一個,因此即使有其他地方(統計SDK經常使用)使用了這個也沒有影響。

判斷Activity的顯示和隱藏需要使用Activity生命週期中成對出現的方法,在顯示的時候設定為前台,在隱藏的時候設定為後台。

首先考慮的是onStart/onStop,但是很快發現了問題,在一個Activity中start另一個Activity,第一個Activity的onStop方法是在第二個Activity的onStart之後執行的,會導致最後一次判定前後台發生錯誤。把onStart簡記為左括弧,onStop簡記為右括弧,則執行完啟動另一個Activity的操作之後,執行的序列為:"(()",可以看出仍有Activity在顯示狀態,但最後一次執行的卻是onStop,而onStop就會去設定為後台狀態,所以狀態是不對的。也可以通過其他手段糾正這個邏輯,但無疑比較複雜。

可以簡單地使用onResume/onPause來替代onStart/onStop,這兩個方法的調用序列用括弧形式表示是這樣的:"()(",最後有Activity為顯示狀態,最後的調用也是onResume設定前台的方法。因此採用onResume/onPause來判斷前背景狀態。

定義一個負責後台判斷和管理的類,這個類實現Application.ActivityLifecycleCallbacks來監聽Activity聲明周期變化,並維護目前狀態和分髮狀態改變回調。

package com.ajeyone.sample1;

import android.app.Activity;import android.app.Application;import android.os.Bundle;import android.os.Handler;import android.util.Log;import java.util.ArrayList;public final class BackgroundManager implements Application.ActivityLifecycleCallbacks {
public interface BackgroundListener { // 提供給外部使用的回調 void onBackgroundStateChanged(); // 發生變化時回調,可通過isBackground方法判斷目前狀態 } private static final String TAG = "BackgroundManager"; private boolean mBackground; private final long mDelay; private final ArrayList<BackgroundListener> mBackgroundListeners = new ArrayList<>(); private final Handler mHandler = new Handler(); private final Runnable mChangeToBackgroundRunnable = new Runnable() { // 順延強制的Runnable,設定為後台有一個延遲 @Override public void run() { setBackground(true); } }; BackgroundManager(long delay) { // 包存取權限,不能在其他地方隨意建立對象,當然使用singleton也可以。 mDelay = delay; // delay時間由外部決定 } public void registerBackgroundListener(BackgroundListener listener) { // 需要監聽可以使用這個方法註冊回調 synchronized (mBackgroundListeners) { mBackgroundListeners.add(listener); } } public void unregisterBackgroundListener(BackgroundListener listener) { // 保證不使用的時候登出,尤其是Activity使用時 synchronized (mBackgroundListeners) { mBackgroundListeners.remove(listener); } } public boolean isBackground() { return mBackground; } private void setBackground(boolean background) { Log.d(TAG, "setBackground: " + background); boolean old = mBackground; mBackground = background; if (old != background) { // 防止多餘的回調,只有在發生變化時才通知 Log.d(TAG, "setBackground: state changed"); for (BackgroundListener listener : mBackgroundListeners) { listener.onBackgroundStateChanged(); } } } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.d(TAG, "onActivityCreated: " + activity); } @Override public void onActivityStarted(Activity activity) { Log.d(TAG, "onActivityStarted: " + activity); } @Override public void onActivityResumed(Activity activity) { Log.d(TAG, "onActivityResumed: " + activity); mHandler.removeCallbacks(mChangeToBackgroundRunnable); // 取消延時執行的Runnable setBackground(false); // 只要顯示出來,直接設定為前台,如果沒顯示前就已經是前台,也不會發生回調 } @Override public void onActivityPaused(Activity activity) { Log.d(TAG, "onActivityPaused: " + activity); mHandler.postDelayed(mChangeToBackgroundRunnable, mDelay); // 隱藏後開始計時,順延強制後台轉換 } @Override public void onActivityStopped(Activity activity) { Log.d(TAG, "onActivityStopped: " + activity); } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { Log.d(TAG, "onActivitySaveInstanceState: " + activity); } @Override public void onActivityDestroyed(Activity activity) { Log.d(TAG, "onActivityDestroyed: " + activity); }}

使用自訂的Application類:提供擷取BackgroundManager的方法和註冊Callback

package com.ajeyone.sample1;import android.app.Application;public class MyApplication extends Application {    private static final long BACKGROUND_DELAY_MS = 30000;    private static MyApplication sInstance;    private BackgroundManager mBackgroundManager;    @Override    public void onCreate() {        super.onCreate();        sInstance = this;        mBackgroundManager = new BackgroundManager(BACKGROUND_DELAY_MS);        registerActivityLifecycleCallbacks(mBackgroundManager);    }    public static MyApplication getInstance() {        return sInstance;    }    public BackgroundManager getBackgroundManager() {        return mBackgroundManager;    }}

需要監聽的Activity:

package com.ajeyone.sample1;import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;public class MainActivity extends AppCompatActivity implements BackgroundManager.BackgroundListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        MyApplication.getInstance().getBackgroundManager().registerBackgroundListener(this);    }    @Override    protected void onDestroy() {        super.onDestroy();        MyApplication.getInstance().getBackgroundManager().unregisterBackgroundListener(this); // 不要忘記登出    }    @Override    public void onBackPressed() {        moveTaskToBack(true);    }    private void showBackgroundState() {        boolean background = MyApplication.getInstance().getBackgroundManager().isBackground();        Log.d("Main", "showBackgroundState: " + background);    }    @Override    public void onBackgroundStateChanged() {        showBackgroundState();    }    public void onOpenDetail(View view) {        startActivity(new Intent(this, DetailActivity.class)); // 開啟另一個Activity,查看前後台效果    }}

 代碼在github上:samplebackground

安卓程式進入後台和前台的判斷

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.