Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發中關於獲取當前Activity的一些思考

Android開發中關於獲取當前Activity的一些思考

編輯:關於Android編程

在Android開發過程中,我們有時候需要獲取當前的Activity實例,比如彈出Dialog操作,必須要用到這個。關於如何實現由很多種思路,這其中有的簡單,有的復雜,這裡簡單總結一下個人的一些經驗吧。

反射

反射是我們經常會想到的方法,思路大概為

  • 獲取ActivityThread中所有的ActivityRecord
  • 從ActivityRecord中獲取狀態不是pause的Activity並返回

一個使用反射來實現的代碼大致如下

public static Activity getActivity() {
  Class activityThreadClass = null;
  try {
    activityThreadClass = Class.forName("android.app.ActivityThread");
    Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
    Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
    activitiesField.setAccessible(true);
    Map activities = (Map) activitiesField.get(activityThread);
    for (Object activityRecord : activities.values()) {
      Class activityRecordClass = activityRecord.getClass();
      Field pausedField = activityRecordClass.getDeclaredField("paused");
      pausedField.setAccessible(true);
      if (!pausedField.getBoolean(activityRecord)) {
        Field activityField = activityRecordClass.getDeclaredField("activity");
        activityField.setAccessible(true);
        Activity activity = (Activity) activityField.get(activityRecord);
        return activity;
      }
    }
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  } catch (NoSuchFieldException e) {
    e.printStackTrace();
  }
  return null;
}

然而這種方法並不是很推薦,主要是有以下的不足:

  • 反射通常會比較慢
  • 不穩定性,這個才是不推薦的原因,Android框架代碼存在修改的可能性,誰要無法100%保證mActivities,paused固定不變。所以可靠性不是完全可靠。

Activity基類

既然反射不是很可靠,那麼有一種比較可靠的方式,就是使用Activity基類。

在Activity的onResume方法中,將當前的Activity實例保存到一個變量中。

public class BaseActivity extends Activity{

  @Override
  protected void onResume() {
    super.onResume();
    MyActivityManager.getInstance().setCurrentActivity(this);
  }
}

然而,這一種方法也不僅完美,因為這種方法是基於約定的,所以必須每個Activity都繼承BaseActivity,如果一旦出現沒有繼承BaseActivity的就可能有問題。

回調方法

介紹了上面兩種不是盡善盡美的方法,這裡實際上還是有一種更便捷的方法,那就是通過Framework提供的回調來實現。

Android自 API 14開始引入了一個方法,即Application的registerActivityLifecycleCallbacks方法,用來監聽所有Activity的生命周期回調,比如onActivityCreated,onActivityResumed等。

So,一個簡單的實現如下

public class MyApplication extends Application {


  @Override
  public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
      @Override
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

      }

      @Override
      public void onActivityStarted(Activity activity) {

      }

      @Override
      public void onActivityResumed(Activity activity) {
        MyActivityManager.getInstance().setCurrentActivity(activity);
      }

      @Override
      public void onActivityPaused(Activity activity) {

      }

      @Override
      public void onActivityStopped(Activity activity) {

      }

      @Override
      public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

      }

      @Override
      public void onActivityDestroyed(Activity activity) {

      }
    });
  }
}

然而,金無足赤人無完人,這種方法唯一的遺憾就是只支持API 14即其以上。不過還在現在大多數設備都滿足了這個要求。

為什麼是弱引用

可能有人會帶著疑問看到這裡,MyActivityManager是個什麼鬼,好,我們現在看一下這個類的實現

public class MyActivityManager {
  private static MyActivityManager sInstance = new MyActivityManager();
  private WeakReference<Activity> sCurrentActivityWeakRef;


  private MyActivityManager() {

  }

  public static MyActivityManager getInstance() {
    return sInstance;
  }

  public Activity getCurrentActivity() {
    Activity currentActivity = null;
    if (sCurrentActivityWeakRef != null) {
      currentActivity = sCurrentActivityWeakRef.get();
    }
    return currentActivity;
  }

  public void setCurrentActivity(Activity activity) {
    sCurrentActivityWeakRef = new WeakReference<Activity>(activity);
  }


}

這個類,實現了當前Activity的設置和獲取。

那麼為什麼要使用弱引用持有Activity實例呢?

其實最主要的目的就是避免內存洩露,因為使用默認的強引用會導致Activity實例無法釋放,導致內存洩露的出現。

以上就是本文的全部內容,希望對大家學習Android軟件編程有所幫助。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved