亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android使用Fragment打造萬能頁面切換框架

2020-04-11 11:03:40
字體:
來源:轉載
供稿:網友

首先我們來回憶一下傳統用Activity進行的頁面切換,activity之間切換,首先需要新建intent對象,給該對象設置一些必須的參數,然后調用startActivity方法進行頁面跳轉。如果需要activity返回結果,則調用startActivityForResult方法,在onActivityResult方法中獲得返回結果。此外,每一個要展示的activity需要在AndroidManifest.xml文件中注冊。而且,如果在某些特定的情況下(比如65536方法數爆炸)要動態加載dex,還得手動管理activity的生命周期。那么,有沒有這么一種方法進行頁面切換時,無需在AndroidManifest.xml文件中聲明這些信息,動態加載時又無需我們管理生命周期,等等優點呢。

我們來回憶一下,在android3.0之后,谷歌出了一個Fragment,這個東西依賴于activity,其生命周期由宿主activity進行管理,并且可以通過FragmentManager和FragmentTransaction等相關的類進行管理。那么我們能不能從Fragment入手,打造一個完全由Fragment組成的頁面跳轉框架呢。

使用Fragment其實很簡單,首先開啟一個事務,通過add,replace,remove等方法進行添加,替換,移除等操作,這一切的操作可能需要依賴一個容器,這個容器提供一個id,進行對應操作時將這個id作為參數傳入。之后通過相應方法提交事務就可以了,就像這樣子。

  • FragmentManager fragmentManager = getSupportFragmentManager(); 
  • FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
  • fragmentTransaction.replace(R.id.fragment_container, fragment); 
  • fragmentTransaction.commit(); 

然而我相信你一定有這樣的經歷,在使用Fragment進行頁面切換時又得不斷用代碼控制其顯示與隱藏的邏輯,那么有沒有這樣一種方法在程序中不斷復用這段代碼呢?

首先,我們希望Fragment能像Activity那樣,進行正確的跳轉。那么需要什么,答案是Fragment對象,我們肯定需要它的Class全類名,當然跳轉的時候可能會帶上一些參數,這個參數應該通過Bundle進行傳遞。而且,全類名可能太長,不便記憶,我們參考web的架構,應該還要取一個別名alias。就這樣,一個Fragment頁面的三個基本屬性就被我們抽取出來了,組成了如下的實體類。在這個實體類中,頁面傳遞的參數為json形式的String字符串對象,在需要使用的時候我們通過該json構造出bundle。頁面名變量mName是整個程序唯一標示該頁面的參數,其值唯一,但是其對應的class全類名可以不唯一,也就是說從name到class的映射可以一對多。

public class CorePage implements Serializable {  private static final long serialVersionUID = 3736359137726536495L;  private String mName;  //頁面名  private String mClazz;  //頁面class  private String mParams;  //傳入參數,json object結構  public CorePage(String name, String clazz, String params) {    mName = name;    mClazz = clazz;    mParams = params;  }  public String getClazz() {    return mClazz;  }  public void setClazz(String clazz) {    mClazz = clazz;  }  public String getName() {    return mName;  }  public void setName(String name) {    mName = name;  }  public String getParams() {    return mParams;  }  public void setParams(String params) {    mParams = params;  }  @Override  public String toString() {    return "Page{" +        "mName='" + mName + '/'' +        ", mClazz='" + mClazz + '/'' +        ", mParams='" + mParams + '/'' +        '}';  }}

實體類編寫好了,為了更方便的進行頁面跳轉,我們需要像Activity那樣,有一個配置文件,里面存著Fragment名到其全類名的映射關系。那么這些數據存在哪呢。我們參考網絡數據,一般從網絡上獲取的數據有兩種格式,一種是json,一種是xml,json由于其優點,在網絡傳輸中被大量使用,這里,我們優先使用json,選定了json之后,就要選定一個json解析的框架,我們不使用android系統自帶的,我們使用阿里的fastjson,當然你也可以使用gson或者jackson。我們的Fragment有很多,所以這個Fragment的配置文件應該是一個json數組。就像這個樣子

[ {  "name": "test1",  "class": "cn.edu.zafu.corepage.sample.TestFragment1",  "params": {   "param1": "value1",   "param2": "value2"  } }, {  "name": "test2",  "class": "cn.edu.zafu.corepage.sample.TestFragment2",  "params": "" }]

有了這個配置,我們就要在程序進入時讀取這個配置。我們將這個配置放在assets目錄下,當然你也可以放在其他目錄下,只有你能讀取到就行,甚至你可以放在壓縮包里。然而,實際情況下,這個文件不應該暴露,因為一旦暴露就存在風險。因此,大家可以采用更安全的方式存這些數據,比如把數據壓縮到壓縮包中,增加一個密碼,而讀取文件的內容的代碼我們移到native中取實現,畢竟java層太容易被反編譯了,而c/c++層相對來說會畢竟有難度。

這里為了簡單,我們暫時放在assets目錄下,那么要從assets目錄中讀取這個文件內容就必須有這么一個讀取該目錄下文件的函數,該目錄在android中也算是一個比較特殊的目錄了,可以通過getAssets()函數,然后獲得一個輸入流,將文件內容讀出,然后將對應的json解析出來就可以了。

  /**   * 從assets目錄下讀取文件   *   * @param context 上下文   * @param fileName 文件名   * @return   */  private String readFileFromAssets(Context context, String fileName) {    String result = "";    try {      InputStreamReader inputReader = new InputStreamReader(context.getResources().getAssets().open(fileName));      BufferedReader bufReader = new BufferedReader(inputReader);      String line = "";      while ((line = bufReader.readLine()) != null)        result += line;    } catch (Exception e) {      e.printStackTrace();    }    return result;  }

然后根據該文件內容讀取json配置。讀取出來后需要將這些數據保存下來。因此要有一個數據結構來保存這個對象,存完之后還要方便取出,存取的依據應該是Fragment的表示,即前面提到的name,因此Map這個數據結構是最適合不過了。

private Map<String, CorePage> mPageMap = new HashMap<String, CorePage>();//保存page的map

將配置讀取出來存進該map,讀取的時候判斷name和class是否為空,為空則跳過。

/** * 從配置文件中讀取page */private void readConfig() {  Log.d(TAG, "readConfig from json");  String content = readFileFromAssets(mContext, "page.json");  JSONArray jsonArray = JSON.parseArray(content);  Iterator<Object> iterator = jsonArray.iterator();  JSONObject jsonPage = null;  String pageName = null;  String pageClazz = null;  String pageParams = null;  while (iterator.hasNext()) {    jsonPage = (JSONObject) iterator.next();    pageName = jsonPage.getString("name");    pageClazz = jsonPage.getString("class");    pageParams = jsonPage.getString("params");    if (TextUtils.isEmpty(pageName) || TextUtils.isEmpty(pageClazz)) {      Log.d(TAG, "page Name is null or pageClass is null");      return;    }    mPageMap.put(pageName, new CorePage(pageName, pageClazz, pageParams));    Log.d(TAG, "put a page:" + pageName);  }  Log.d(TAG, "finished read pages,page size:" + mPageMap.size());}

此外,除了從配置文件中讀取,我們應該可以動態添加,對外提供這個函數。

  /**   * 新增新頁面   *   * @param name 頁面名   * @param clazz 頁面class   * @param params 頁面參數   * @return 是否新增成功   */  public boolean putPage(String name, Class<? extends BaseFragment> clazz, Map<String, String> params) {    if (TextUtils.isEmpty(name) || clazz == null) {      Log.d(TAG, "page Name is null or pageClass is null");      return false;    }    if (mPageMap.containsKey(name)) {      Log.d(TAG, "page has already put!");      return false;    }    CorePage corePage = new CorePage(name, clazz.getName(), buildParams(params));    Log.d(TAG, "put a page:" + name);    return true;  }  /**   * 從hashMap中得到參數的json格式   *   * @param params 頁面map形式參數   * @return json格式參數   */  private String buildParams(Map<String, String> params) {    if (params == null) {      return "";    }    String result = JSON.toJSONString(params);    Log.d(TAG, "params:" + result);    return result;  }

文章開頭已經說了,頁面跳轉的參數是json形式的字符串,我們還要這么一個函數,能夠根據json字符串構造出一個bundle

/**   * 根據page,從pageParams中獲得bundle   *   * @param corePage 頁面   * @return 頁面的參數   */  private Bundle buildBundle(CorePage corePage) {    Bundle bundle = new Bundle();    String key = null;    Object value = null;    if (corePage != null && corePage.getParams() != null) {      JSONObject j = JSON.parseObject(corePage.getParams());      if (j != null) {        Set<String> keySet = j.keySet();        if (keySet != null) {          Iterator<String> ite = keySet.iterator();          while (ite.hasNext()) {            key = ite.next();            value = j.get(key);            bundle.putString(key, value.toString());          }        }      }    }    return bundle;  }

以上配置讀取的一系列函數,構成了頁面管理類CorePageManager,我們對其應用單例模式。


/** * 跳轉頁面管理 */public class CorePageManager {  private volatile static CorePageManager mInstance = null;  //單例  private Context mContext;  //Context上下文  /**   * 構造函數私有化   */  private CorePageManager() {  }  /**   * 獲得單例   *   * @return PageManager   */  public static CorePageManager getInstance() {    if (mInstance == null) {      synchronized (CorePageManager.class) {        if (mInstance == null) {          mInstance = new CorePageManager();        }      }    }    return mInstance;  }  /**   * 初始化配置   *   * @param context 上下文   */  public void init(Context context) {    try {      mContext = context.getApplicationContext();      readConfig();    } catch (Exception e) {      e.printStackTrace();    }  }}

其中init函數暴露給程序入口,進行配置文件的讀取。一般放在Application的子類的onCreate方法中即可。

到這里為止,基本上我們一切已經就緒了。就差如何切換了。這里,在CorePageManager類中再提供兩個核心函數,用于處理頁面切換。

下面這個函數是頁面切換的核心函數,首先根據參數從map中拿到對應的實體類,假設存在這個頁面,通過class名用反射獲得該Fragment對象,調用前面寫好的創建Bundle的函數得到頁面參數,并與當前函數中的入參bundle進行合并。將參數設置給fragment對象,開啟一個fragment事務,查找id為fragment_container的fragment容器,如果該容器已經有fragment,則隱藏它,如果該函數傳遞了動畫參數,則添加頁面切換動畫,然后將反射獲得的fragment對象添加到該容器中,如果需要添加到返回棧,則調用addToBackStack,最后提交事務并返回該fragment對象。

整個函數很簡單,就是我們平常在activity中寫的切換fragment的代碼

 /**   * 頁面跳轉核心函數之一   * 打開一個fragemnt   *   * @param fragmentManager FragmentManager管理類   * @param pageName 頁面名   * @param bundle 參數   * @param animations 動畫類型   * @param addToBackStack 是否添加到返回棧   * @return   */  public Fragment openPageWithNewFragmentManager(FragmentManager fragmentManager, String pageName, Bundle bundle, int[] animations, boolean addToBackStack) {    BaseFragment fragment = null;    try {      CorePage corePage = this.mPageMap.get(pageName);      if (corePage == null) {        Log.d(TAG, "Page:" + pageName + " is null");        return null;      }      fragment = (BaseFragment) Class.forName(corePage.getClazz()).newInstance();      Bundle pageBundle = buildBundle(corePage);      if (bundle != null) {        pageBundle.putAll(bundle);      }      fragment.setArguments(pageBundle);      fragment.setPageName(pageName);      FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();      if (animations != null && animations.length >= 4) {        fragmentTransaction.setCustomAnimations(animations[0], animations[1], animations[2], animations[3]);      }      Fragment fragmentContainer = fragmentManager.findFragmentById(R.id.fragment_container);      if (fragmentContainer != null) {        fragmentTransaction.hide(fragmentContainer);      }      fragmentTransaction.add(R.id.fragment_container, fragment, pageName);      if (addToBackStack) {        fragmentTransaction.addToBackStack(pageName);      }      fragmentTransaction.commitAllowingStateLoss();      //fragmentTransaction.commit();    } catch (Exception e) {      e.printStackTrace();      Log.d(TAG, "Fragment.error:" + e.getMessage());      return null;    }    return fragment;  }

而上面這個函數中的id值在一個基礎的布局中,之后的Fragment都會添加到該布局中去。我們的基類Activity也將使用這個布局,這個后續編寫BaseActivity的時候會提到

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:id="@+id/fragment_container"  android:layout_width="fill_parent"  android:layout_height="fill_parent" ></FrameLayout>

此外,我們再提供一個核心函數。就是如果返回棧中存在了目標fragment,則將其彈出,否則新建fragment打開。

 /**   * 頁面跳轉核心函數之一   * 打開一個Fragement,如果返回棧中有則出棧,否則新建   *   * @param fragmentManager FragmentManager管理類   * @param pageName 頁面別名   * @param bundle 參數   * @param animations 動畫   * @return 成功跳轉到的fragment   */  public Fragment gotoPage(FragmentManager fragmentManager, String pageName, Bundle bundle, int[] animations) {    Log.d(TAG, "gotoPage:" + pageName);    Fragment fragment = null;    if (fragmentManager != null) {      fragment = fragmentManager.findFragmentByTag(pageName);    }    if (fragment != null) {      fragmentManager.popBackStackImmediate(pageName, 0);    } else {      fragment = this.openPageWithNewFragmentManager(fragmentManager, pageName, bundle, animations, true);    }    return fragment;  }

細心的你可能已經注意到了頁面跳轉函數中用到了動畫,其實這個動畫是一個數組,為了方便使用,我們將其封裝為枚舉類,提供常見的幾種動畫形式。

package cn.edu.zafu.corepage.core;/** * 頁面切換動畫類別 */public enum CoreAnim {  none, /* 沒有動畫 */  present, /*由下到上動畫 */  slide,/* 從左到右動畫 */  fade;/*漸變 */}

之后我們還要根據該枚舉類獲得對應的動畫的xml文件。

/**   * 動畫轉化,根據枚舉類返回int數組   *   * @param coreAnim   * @return   */  public static int[] convertAnimations(CoreAnim coreAnim) {    if (coreAnim == CoreAnim.present) {      int[] animations = {R.anim.push_in_down, R.anim.push_no_ani, R.anim.push_no_ani, R.anim.push_out_down};      return animations;    } else if (coreAnim == CoreAnim.fade) {      int[] animations = {R.anim.alpha_in, R.anim.alpha_out, R.anim.alpha_in, R.anim.alpha_out};      return animations;    } else if (coreAnim == CoreAnim.slide) {      int[] animations = {R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right};      return animations;    }    return null;  }

這里貼出一個alpha_in.xml中的代碼,其他文件類似,這些文件都位于res/anim目錄下

<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android"  android:duration="@android:integer/config_mediumAnimTime"  android:fromAlpha="0.0"  android:toAlpha="1.0" />

到了這里,如果你都明白了,那么后面基本上就沒有什么難度了,因為之后的功能都是基于以上內容。

前面我們定義了一個CorePage實體類用于保存配置文件中實體類的信息,而頁面切換過程中需要傳遞一些參數,比如是否添加到fragment返回棧,是否在新的activity中打開fragment,頁面切換時的動畫,傳遞的參數等等,通樣,我們將其封裝為實體類。由于該對象可能需要通過intent傳遞,這里我們將其實現Parcelable接口。實現該接口方法很簡單,假設使用的是android studio,使用快捷鍵alt+insert選擇Parcelable即可創建一個模板,我們將其補齊就好了。整個類如下,我們對外提供了多個重載的構造函數,其本質都是一樣的,而前面的動畫轉換函數我們將其放入這個類中。

/** * 頁面跳轉控制參數 */public class CoreSwitchBean implements Parcelable {  public static final Parcelable.Creator<CoreSwitchBean> CREATOR = new Parcelable.Creator<CoreSwitchBean>() {    @Override    public CoreSwitchBean createFromParcel(Parcel in) {      return new CoreSwitchBean(in);    }    @Override    public CoreSwitchBean[] newArray(int size) {      return new CoreSwitchBean[size];    }  };  private String mPageName;  //頁面名  private Bundle mBundle;  //相關數據  private int[] mAnim = null;  //動畫類型  private boolean mAddToBackStack = true;  //是否添加到棧中  private boolean mNewActivity = false;  //是否起新的Activity  private int requestCode = -1;  //fragment跳轉  public CoreSwitchBean(String pageName) {    this.mPageName = pageName;  }  public CoreSwitchBean(String pageName, Bundle bundle) {    this.mPageName = pageName;    this.mBundle = bundle;  }  public CoreSwitchBean(String pageName, Bundle bundle, CoreAnim coreAnim) {    this.mPageName = pageName;    this.mBundle = bundle;    this.setAnim(coreAnim);  }  public void setAnim(CoreAnim anim) {    mAnim = convertAnimations(anim);  }  /**   * 動畫轉化,根據枚舉類返回int數組   *   * @param coreAnim   * @return   */  public static int[] convertAnimations(CoreAnim coreAnim) {    if (coreAnim == CoreAnim.present) {      int[] animations = {R.anim.push_in_down, R.anim.push_no_ani, R.anim.push_no_ani, R.anim.push_out_down};      return animations;    } else if (coreAnim == CoreAnim.fade) {      int[] animations = {R.anim.alpha_in, R.anim.alpha_out, R.anim.alpha_in, R.anim.alpha_out};      return animations;    } else if (coreAnim == CoreAnim.slide) {      int[] animations = {R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right};      return animations;    }    return null;  }  public CoreSwitchBean(String pageName, Bundle bundle, int[] anim) {    this.mPageName = pageName;    this.mBundle = bundle;    this.mAnim = anim;  }  public CoreSwitchBean(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack) {    this.mPageName = pageName;    this.mBundle = bundle;    this.setAnim(coreAnim);    this.mAddToBackStack = addToBackStack;  }  public CoreSwitchBean(String pageName, Bundle bundle, int[] anim, boolean addToBackStack) {    this.mPageName = pageName;    this.mBundle = bundle;    this.mAnim = anim;    this.mAddToBackStack = addToBackStack;  }  public CoreSwitchBean(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack, boolean newActivity) {    this.mPageName = pageName;    this.mBundle = bundle;    this.setAnim(coreAnim);    this.mAddToBackStack = addToBackStack;    this.mNewActivity = newActivity;  }  public CoreSwitchBean(String pageName, Bundle bundle, int[] anim, boolean addToBackStack, boolean newActivity) {    this.mPageName = pageName;    this.mBundle = bundle;    this.mAnim = anim;    this.mAddToBackStack = addToBackStack;    this.mNewActivity = newActivity;  }  public CoreSwitchBean(String pageName, Bundle bundle, int[] anim, boolean addToBackStack, boolean newActivity, int requestCode) {    this.mPageName = pageName;    this.mBundle = bundle;    this.mAnim = anim;    this.mAddToBackStack = addToBackStack;    this.mNewActivity = newActivity;    this.requestCode = requestCode;  }  protected CoreSwitchBean(Parcel in) {    mPageName = in.readString();    mBundle = in.readBundle();    int[] a = {in.readInt(), in.readInt(), in.readInt(), in.readInt()};    mAnim = a;    mAddToBackStack = in.readInt() == 1 ? true : false;    mNewActivity = in.readInt() == 1 ? true : false;    requestCode = in.readInt();  }  public String getPageName() {    return mPageName;  }  public void setPageName(String pageName) {    mPageName = pageName;  }  public boolean isNewActivity() {    return mNewActivity;  }  public void setNewActivity(boolean newActivity) {    mNewActivity = newActivity;  }  public boolean isAddToBackStack() {    return mAddToBackStack;  }  public void setAddToBackStack(boolean addToBackStack) {    mAddToBackStack = addToBackStack;  }  public int[] getAnim() {    return mAnim;  }  public void setAnim(int[] anim) {    mAnim = anim;  }  public Bundle getBundle() {    return mBundle;  }  public void setBundle(Bundle bundle) {    mBundle = bundle;  }  public int getRequestCode() {    return requestCode;  }  public void setRequestCode(int requestCode) {    this.requestCode = requestCode;  }  @Override  public String toString() {    return "SwitchBean{" +        "mPageName='" + mPageName + '/'' +        ", mBundle=" + mBundle +        ", mAnim=" + Arrays.toString(mAnim) +        ", mAddToBackStack=" + mAddToBackStack +        ", mNewActivity=" + mNewActivity +        ", requestCode=" + requestCode +        '}';  }  @Override  public int describeContents() {    return 0;  }  @Override  public void writeToParcel(Parcel out, int flags) {    if (mPageName == null) {      mPageName = "";    }    if (mBundle == null) {      mBundle = new Bundle();    }    if (mAnim == null) {      int[] a = {-1, -1, -1, -1};      mAnim = a;    }    out.writeString(mPageName);    mBundle.writeToParcel(out, flags);    if (mAnim != null && mAnim.length == 4) {      out.writeInt(mAnim[0]);      out.writeInt(mAnim[1]);      out.writeInt(mAnim[2]);      out.writeInt(mAnim[3]);    } else {      out.writeInt(-1);      out.writeInt(-1);      out.writeInt(-1);      out.writeInt(-1);    }    out.writeInt(mAddToBackStack ? 1 : 0);    out.writeInt(mNewActivity ? 1 : 0);    out.writeInt(requestCode);  }}

該類中的部分屬性有一些默認值,比如是否添加到返回棧,是否起新Activity,我們默認在當前activity中打開fragment,并且添加到返回棧。有了這個類,之后的頁面切換都通過該實體類進行傳參就可以了。

然后,我們定義一個接口,讓基類activity實現該接口,用于切換時的一些常用操作。fragment中調用宿主activity中該接口的方法即可。

/** * 頁面跳轉接口,用于控制頁面跳轉或啟動新的activity */public interface CoreSwitcher {  /**   * 返回到前一個頁面(只有一個fragment時會關閉Activityt)   */  void popPage();  /**   * fragmentTag 是否在當前頂上activity上的最頂上的fragment   *   * @param fragmentTag   * @return   */  boolean isFragmentTop(String fragmentTag);  /**   * 是否查找到某個page   *   * @param pageName   * @return   */  boolean findPage(final String pageName);  /**   * 跳轉到某一個頁面。   *   * @param bean   * @return   */  Fragment gotoPage(CoreSwitchBean bean);  /**   * 打開一個新的頁面   *   * @param bean   * @return   */  Fragment openPage(CoreSwitchBean bean);  /**   * 移除當前Acitivity不需要的fragment   *   * @param fragmentLists   */  void removeUnlessFragment(List<String> fragmentLists);  /**   * 頁面跳轉,支持跨Activity進行傳遞數據   *   * @param page   * @param fragment   * @return   */  public Fragment openPageForResult(final CoreSwitchBean page, final BaseFragment fragment);}

到了這里,似乎已經初具模型了,接下來,我們實現該接口。為了保證在子線程中也能調用這些方法,我們需要一個主線程的handler來幫我們完成一部分工作。假設我們已經獲得了這個handler。具體細節看下面的代碼實現吧,仔細閱讀以下不難理解的。

  private static List<WeakReference<BaseActivity>> mActivities = new ArrayList<WeakReference<BaseActivity>>();  //所有activity的引用  private Handler mHandler = null;  //線程安全的handler  private WeakReference<BaseActivity> mCurrentInstance = null;  //當前activity的引用  /**   * 彈出頁面   */  @Override  public void popPage() {    popOrFinishActivity();    //如果只有一個Fagment則退出activty  }  /**   * 保證在主線程操作   */  private void popOrFinishActivity() {    if (this.isFinishing()) {      return;    }    if (this.getSupportFragmentManager().getBackStackEntryCount() > 1) {      if (isMainThread()) {        this.getSupportFragmentManager().popBackStackImmediate();      } else {        this.mHandler.post(new Runnable() {          @Override          public void run() {            getSupportFragmentManager().popBackStackImmediate();          }        });      }    } else {      finishActivity(this, true);    }  }  /**   * 是否是主線程   * @return   */  private boolean isMainThread() {    return Thread.currentThread() == this.getMainLooper().getThread();  }  /**   * 是否位于棧頂   * @param fragmentTag   * @return   */  @Override  public boolean isFragmentTop(String fragmentTag) {    int size = mActivities.size();    if (size > 0) {      WeakReference<BaseActivity> ref = mActivities.get(size - 1);      BaseActivity item = ref.get();      if (item != null && item == this) {        FragmentActivity activity = item;        FragmentManager manager = activity.getSupportFragmentManager();        if (manager != null) {          int count = manager.getBackStackEntryCount();          if (count >= 1) {            FragmentManager.BackStackEntry entry = manager.getBackStackEntryAt(count - 1);            if (entry.getName().equalsIgnoreCase(fragmentTag)) {              return true;            }          }        }      }    }    return false;  }  /**   * 查找fragment   * @param pageName   * @return   */  @Override  public boolean findPage(String pageName) {    int size = mActivities.size();    int j = size - 1;    boolean hasFind = false;    for (; j >= 0; j--) {      WeakReference<BaseActivity> ref = mActivities.get(j);      if (ref != null) {        BaseActivity item = ref.get();        if (item == null) {          Log.d(TAG, "item is null");          continue;        }        FragmentManager manager = item.getSupportFragmentManager();        int count = manager.getBackStackEntryCount();        for (int i = count - 1; i >= 0; i--) {          String name = manager.getBackStackEntryAt(i).getName();          if (name.equalsIgnoreCase(pageName)) {            hasFind = true;            break;          }        }        if (hasFind) {          break;        }      }    }    return hasFind;  }  /**   * 彈出并用bundle刷新數據,在onFragmentDataReset中回調   * @param page   * @return   */  @Override  public Fragment gotoPage(CoreSwitchBean page) {    if (page == null) {      Log.e(TAG, "page name empty");      return null;    }    String pageName = page.getPageName();    if (!findPage(pageName)) {      Log.d(TAG, "Be sure you have the right pageName" + pageName);      return this.openPage(page);    }    int size = mActivities.size();    int i = size - 1;    for (; i >= 0; i--) {      WeakReference<BaseActivity> ref = mActivities.get(i);      if (ref != null) {        BaseActivity item = ref.get();        if (item == null) {          Log.d(TAG, "item null");          continue;        }        boolean findInActivity = popFragmentInActivity(pageName, page.getBundle(), item);        if (findInActivity) {          break;        } else {          item.finish();          // 找不到就彈出        }      }    }    return null;  }  /**   * 當前activiti中彈fragment   * @param pageName   * @param bundle   * @param findAcitivity   * @return   */  protected boolean popFragmentInActivity(final String pageName, Bundle bundle, BaseActivity findAcitivity) {    if (pageName == null || findAcitivity == null || findAcitivity.isFinishing()) {      return false;    } else {      final FragmentManager fragmentManager = findAcitivity.getSupportFragmentManager();      if (fragmentManager != null) {        Fragment frg = fragmentManager.findFragmentByTag(pageName);        if (frg != null && frg instanceof BaseFragment) {          if (fragmentManager.getBackStackEntryCount() > 1 && mHandler != null) {            mHandler.postDelayed(new Runnable() {              @Override              public void run() {                fragmentManager.popBackStack(pageName, 0);              }            }, 100);          }          ((BaseFragment) frg).onFragmentDataReset(bundle);//默認為空實現,用于舒心返回時的頁面數據,重寫改方法完成數據刷新          return true;        }      }    }    return false;  }  /**   * 根據Switchpage打開activity   * @param page   */  public void startActivity(CoreSwitchBean page) {    try {      Intent intent = new Intent(this, BaseActivity.class);      intent.putExtra("SwitchBean", page);      this.startActivity(intent);      int[] animations = page.getAnim();      if (animations != null && animations.length >= 2) {        this.overridePendingTransition(animations[0], animations[1]);      }    } catch (Exception e) {      e.printStackTrace();      Log.e(TAG, e.getMessage());    }  }/**   * 根據SwitchBean打開fragment   * @param page   * @return   */  @Override  public Fragment openPage(CoreSwitchBean page) {    boolean addToBackStack = page.isAddToBackStack();    boolean newActivity = page.isNewActivity();    Bundle bundle = page.getBundle();    int[] animations = page.getAnim();    if (newActivity) {      startActivity(page);      return null;    } else {      String pageName = page.getPageName();      return CorePageManager.getInstance().openPageWithNewFragmentManager(getSupportFragmentManager(), pageName, bundle, animations, addToBackStack);    }  }  /**   * 移除無用fragment   * @param fragmentLists   */  @Override  public void removeUnlessFragment(List<String> fragmentLists) {    if (this.isFinishing()) {      return;    }    FragmentManager manager = getSupportFragmentManager();    if (manager != null) {      FragmentTransaction transaction = manager.beginTransaction();      for (String tag : fragmentLists) {        Fragment fragment = manager.findFragmentByTag(tag);        if (fragment != null) {          transaction.remove(fragment);        }      }      transaction.commitAllowingStateLoss();      int count = manager.getBackStackEntryCount();      if (count == 0) {        this.finish();      }    }  }  /**   * 給BaseFragment調用   * @param page   * @param fragment   * @return   */  @Override  public Fragment openPageForResult(CoreSwitchBean page, BaseFragment fragment) {    if (page != null) {      if (page.isNewActivity()) {        Log.d(TAG,"openPageForResult start new activity-----"+fragment.getPageName());        mFragmentForResult=fragment;        mFragmentRequestCode=page.getRequestCode();        startActivityForResult(page);        return null;      }else{        String pageName=page.getPageName();        Bundle bundle=page.getBundle();        int[] animations=page.getAnim();        boolean addToBackStack=page.isAddToBackStack();        BaseFragment frg = (BaseFragment) CorePageManager.getInstance().openPageWithNewFragmentManager(getSupportFragmentManager(), pageName, bundle, animations, addToBackStack);        if (frg==null){          return null;        }        final BaseFragment opener= fragment;        frg.setRequestCode(page.getRequestCode());        frg.setFragmentFinishListener(new BaseFragment.OnFragmentFinishListener() {          @Override          public void onFragmentResult(int requestCode, int resultCode, Intent intent) {            opener.onFragmentResult(requestCode,resultCode,intent);          }        });        return frg;      }    }else{      Log.d(TAG, "openPageForResult.SwitchBean is null");    }    return null;  }  public void startActivityForResult(CoreSwitchBean page) {    try {      Intent intent = new Intent(this, BaseActivity.class);      intent.putExtra("SwitchBean", page);      intent.putExtra("startActivityForResult", "true");      this.startActivityForResult(intent, page.getRequestCode());      int[] animations = page.getAnim();      if (animations != null && animations.length >= 2) {        this.overridePendingTransition(animations[0], animations[1]);      }    } catch (Exception e) {      e.printStackTrace();    }  }  /**   * 如果是fragment發起的由fragment處理,否則默認處理   * @param requestCode   * @param resultCode   * @param data   */  @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {    Log.d(TAG, "onActivityResult from baseActivity" + requestCode + " " + resultCode);    if (mFragmentRequestCode == requestCode && mFragmentForResult != null) {      mFragmentForResult.onFragmentResult(mFragmentRequestCode, resultCode, data);    }    super.onActivityResult(requestCode, resultCode, data);  }

除此之外,提供一些函數的重載便于調用以及一些工具函數。


  /**   * 僅用于接受應用退出廣播,程序退出時有機會做一些必要的清理工作   */  private BroadcastReceiver mExitReceiver = new BroadcastReceiver() {    @Override    public void onReceive(Context context, Intent intent) {      String action = intent.getAction();      if (action.equals(Config.ACTION_EXIT_APP)) {        Log.d(TAG,"exit from broadcast");        finish();      }    }  };  /**   * 返回最上層的activity   *   * @return   */  public static BaseActivity getTopActivity() {    if (mActivities != null) {      int size = mActivities.size();      if (size >= 1) {        WeakReference<BaseActivity> ref = mActivities.get(size - 1);        if (ref != null) {          return ref.get();        }      }    }    return null;  }  /**   * 廣播退出時清理activity列表   */  public static void unInit() {    if (mActivities != null) {      mActivities.clear();    }  }  /**   * 獲得當前活動頁面名   * @return   */  protected String getPageName() {    BaseFragment frg = getActiveFragment();    if (frg != null) {      return frg.getPageName();    }    return "";  }  /**   * 打開fragment,并設置是否新開activity,設置是否添加到返回棧   *   * @param pageName   * @param bundle   * @param coreAnim   * @param addToBackStack   * @param newActivity   * @return   */  public Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack, boolean newActivity) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, coreAnim, addToBackStack, newActivity);    return openPage(page);  }  /**   * 打開fragment,并設置是否新開activity,設置是否添加到返回棧   *   * @param pageName   * @param bundle   * @param anim   * @param addToBackStack   * @param newActivity   * @return   */  public Fragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack, boolean newActivity) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, anim, addToBackStack, newActivity);    return openPage(page);  }  /**   * 打開fragment,并設置是否添加到返回棧   *   * @param pageName   * @param bundle   * @param coreAnim   * @param addToBackStack   * @return   */  public Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, coreAnim, addToBackStack);    return openPage(page);  }  /**   * 打開fragment,并設置是否添加到返回棧   *   * @param pageName   * @param bundle   * @param anim   * @param addToBackStack   * @return   */  public Fragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, anim, addToBackStack);    return openPage(page);  }  /**   * 打開fragment   *   * @param pageName   * @param bundle   * @param coreAnim   * @return   */  public Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, coreAnim);    return openPage(page);  }  /**   * 打開fragment   *   * @param pageName   * @param bundle   * @param anim   * @return   */  public Fragment openPage(String pageName, Bundle bundle, int[] anim) {    CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, anim);    return openPage(page);  }  /**   * 如果當前activity中只有一個activity,則關閉activity,否則父類處理   */  @Override  public void onBackPressed() {    if (this.getSupportFragmentManager().getBackStackEntryCount() == 1) {      this.finishActivity(this, true);    } else {      super.onBackPressed();    }  }  /**   * 如果fragment中處理了則fragment處理否則activity處理   * @param keyCode   * @param event   * @return   */  @Override  public boolean onKeyDown(int keyCode, KeyEvent event) {    BaseFragment activeFragment = getActiveFragment();    boolean isHanlde = false;    if (activeFragment != null) {      isHanlde = activeFragment.onKeyDown(keyCode, event);    }    if (!isHanlde) {      return super.onKeyDown(keyCode, event);    } else {      return isHanlde;    }  }  /**   * 獲得當前活動fragmnet   *   * @return   */  public BaseFragment getActiveFragment() {    if (this.isFinishing()) {      return null;    }    FragmentManager manager = this.getSupportFragmentManager();    if (manager != null) {      int count = manager.getBackStackEntryCount();      if (count > 0) {        String tag = manager.getBackStackEntryAt(count - 1).getName();        return (BaseFragment) manager.findFragmentByTag(tag);      }    }    return null;  }  /**   * 打印,調試用   */  private void printAllActivities() {    Log.d(TAG, "------------BaseActivity print all------------activities size:" + mActivities.size());    for (WeakReference<BaseActivity> ref : mActivities) {      if (ref != null) {        BaseActivity item = ref.get();        if (item != null) {          Log.d(TAG, item.toString());        }      }    }  }  /**   * 結束activity,設置是否顯示動畫   *   * @param activity   * @param showAnimation   */  private void finishActivity(BaseActivity activity, boolean showAnimation) {    if (activity != null) {      activity.finish();    }    if (showAnimation) {      //動畫      int[] animations = null;      if (activity.mFirstCoreSwitchBean != null && activity.mFirstCoreSwitchBean.getAnim() != null) {        animations = activity.mFirstCoreSwitchBean.getAnim();      }      if (animations != null && animations.length >= 4) {        overridePendingTransition(animations[2], animations[3]);      }    }  }

并在BaseActivity的onCreate方法中完成一些初始化工作。

/** * 頁面跳轉都通過BaseActivity 嵌套Fragment來實現,動態替換fragment只需要指定相應的參數。 避免Activity 需要再manifest中注冊的問題。 * 1.管理應用中所有BaseActivity 實例。 2.管理BaseActivity 實例和fragment的跳轉 */public class BaseActivity extends FragmentActivity implements CoreSwitcher {  private static final String TAG = BaseActivity.class.getSimpleName();  private static List<WeakReference<BaseActivity>> mActivities = new ArrayList<WeakReference<BaseActivity>>();  protected CoreSwitchBean mFirstCoreSwitchBean;//記錄首個,用于頁面切換  //所有activity的引用  private Handler mHandler = null;  private WeakReference<BaseActivity> mCurrentInstance = null;  //當前activity的引用  private BaseFragment mFragmentForResult = null;  //forResult 的fragment  private int mFragmentRequestCode = -1;  //請求碼,必須大于等于0  /**   * 僅用于接受應用退出廣播,程序退出時有機會做一些必要的清理工作   */  private BroadcastReceiver mExitReceiver = new BroadcastReceiver() {    @Override    public void onReceive(Context context, Intent intent) {      String action = intent.getAction();      if (action.equals(Config.ACTION_EXIT_APP)) {        Log.d(TAG,"exit from broadcast");        finish();      }    }  };  @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_base);    Intent mNewIntent = getIntent();    //處理新開activity的情況    if (null != savedInstanceState) {      loadActivitySavedData(savedInstanceState);      //恢復數據      //需要用注解SaveWithActivity    }    mHandler = new Handler(getMainLooper());    //獲得主線程handler    mCurrentInstance = new WeakReference<BaseActivity>(this);    //當前activity弱引用    mActivities.add(mCurrentInstance);    //當前activity增加到activity列表中    printAllActivities();    //打印所有activity情況    init(mNewIntent);    //處理新開activity跳轉    IntentFilter filter = new IntentFilter();    filter.addAction(Config.ACTION_EXIT_APP);    filter.addCategory(Intent.CATEGORY_DEFAULT);    BaseApplication.getLocalBroadcastManager().registerReceiver(mExitReceiver, filter);    //注冊本地廣播,接收程序退出廣播  }}

接下來就是處理基類BaseFragment的問題了,這里貼出該類所有代碼,具體請參考注釋。

public class BaseFragment extends Fragment {  private static final String TAG = BaseFragment.class.getSimpleName();  protected Activity mActivity;  //所在activity  private String mPageName;  //頁面名  private int mRequestCode;  //用于startForResult的requestCode  private CoreSwitcher mPageCoreSwitcher;  //openPageForResult接口,用于傳遞返回結果  private OnFragmentFinishListener mFragmentFinishListener;  /**   * 設置該接口用于返回結果   * @param listener OnFragmentFinishListener對象   */  public void setFragmentFinishListener(OnFragmentFinishListener listener) {    this.mFragmentFinishListener = listener;  }  /**   * 設置openPageForResult打開的頁面的返回結果   * @param resultCode 返回結果碼   * @param intent 返回的intent對象   */  public void setFragmentResult(int resultCode, Intent intent) {    if (mFragmentFinishListener != null) {      mFragmentFinishListener.onFragmentResult(mRequestCode, resultCode, intent);    }  }  /**   * 得到requestCode   * @return 請求碼   */  public int getRequestCode() {    return this.mRequestCode;  }  /**   * 設置requestCode   * @param code 請求碼   */  public void setRequestCode(int code) {    this.mRequestCode = code;  }  /**   * 將Activity中onKeyDown在Fragment中實現,   * @param keyCode   * @param event   * @return   */  public boolean onKeyDown(int keyCode, KeyEvent event) {    return false;  }  /**   * 數據設置,回調   * @param bundle   */  public void onFragmentDataReset(Bundle bundle) {  }  /**   * 彈出棧頂的Fragment。如果Activity中只有一個Fragemnt時,Acitivity也退出。   */  public void popToBack() {    this.popToBack(null, null);  }  /**   * 如果在fragment棧中找到,則跳轉到該fragment中去,否則彈出棧頂   * @param pageName 頁面名   * @param bundle 參數   */  public final void popToBack(String pageName, Bundle bundle) {    CoreSwitcher coreSwitcher = getSwitcher();    if (coreSwitcher != null) {      if (pageName == null) {        coreSwitcher.popPage();      } else {        if (this.findPage(pageName)) {          CoreSwitchBean page = new CoreSwitchBean(pageName, bundle);          coreSwitcher.gotoPage(page);        } else {          coreSwitcher.popPage();        }      }    } else {      Log.d(TAG, "pageSwitcher null");    }  }  /**   * 得到頁面切換Switcher,即BaseActivity   * @return Switcher   */  public CoreSwitcher getSwitcher() {    synchronized (BaseFragment.this) {// 加強保護,保證pageSwitcher 不為null      if (mPageCoreSwitcher == null) {        if (this.mActivity != null && this.mActivity instanceof CoreSwitcher) {          mPageCoreSwitcher = (CoreSwitcher) this.mActivity;        }        if (mPageCoreSwitcher == null) {          BaseActivity topActivity = BaseActivity.getTopActivity();          if (topActivity != null && topActivity instanceof CoreSwitcher) {            mPageCoreSwitcher = (CoreSwitcher) topActivity;          }        }      }    }    return mPageCoreSwitcher;  }  public void setSwitcher(CoreSwitcher pageCoreSwitcher) {    this.mPageCoreSwitcher = pageCoreSwitcher;  }  /**   * 查找fragment是否存在,通過Switcher查找   * @param pageName 頁面名   * @return 是否找到   */  public boolean findPage(String pageName) {    if (pageName == null) {      Log.d(TAG, "pageName is null");      return false;    }    CoreSwitcher coreSwitcher = getSwitcher();    if (coreSwitcher != null) {      return coreSwitcher.findPage(pageName);    } else {      Log.d(TAG, "pageSwitch is null");      return false;    }  }  /**   * 對應fragment是否位于棧頂,通過Switcher查找   * @param fragmentTag fragment的tag   * @return 是否位于棧頂   */  public boolean isFragmentTop(String fragmentTag) {    CoreSwitcher pageCoreSwitcher = this.getSwitcher();    if (pageCoreSwitcher != null) {      return pageCoreSwitcher.isFragmentTop(fragmentTag);    } else {      Log.d(TAG, "pageSwitcher is null");      return false;    }  }  /**   * 重新該方法用于獲得返回的數據   * @param requestCode 請求碼   * @param resultCode 返回結果碼   * @param data 返回數據   */  public void onFragmentResult(int requestCode, int resultCode, Intent data) {    Log.d(TAG, "onFragmentResult from baseFragment:requestCode-" + requestCode + " resultCode-" + resultCode);  }  /**   * 在當前activity中打開一個fragment,并添加到返回棧中   * @param pageName Fragemnt 名,在page.json中配置。   * @param bundle 頁面跳轉時傳遞的參數   * @param coreAnim 指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim) {    return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), true);  }  /**   * 在當前activity中打開一個fragment,并設置是否添加到返回棧   * @param pageName Fragemnt 名,在page.json中配置。   * @param bundle 頁面跳轉時傳遞的參數   * @param anim 指定的動畫農林 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @param addToBackStack 是否添加到用戶操作棧中   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack) {    return this.openPage(pageName, bundle, anim, addToBackStack, false);  }  /**   * 打開一個fragment并設置是否新開activity,設置是否添加返回棧   * @param pageName Fragemnt 名,在page.json中配置。   * @param bundle 頁面跳轉時傳遞的參數   * @param anim 指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @param addToBackStack 是否添加到用戶操作棧中   * @param newActivity 該頁面是否新建一個Activity   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, int[] anim, boolean addToBackStack, boolean newActivity) {    if (pageName == null) {      Log.d(TAG, "pageName is null");      return null;    }    CoreSwitcher coreSwitcher = this.getSwitcher();    if (coreSwitcher != null) {      CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, anim, addToBackStack, newActivity);      return coreSwitcher.openPage(page);    } else {      Log.d(TAG, "pageSwitcher is null");      return null;    }  }  /**   * 在當前activity中打開一個fragment,并添加到返回棧中   *   * @param pageName Fragemnt 名,在page.json中配置。   * @param bundle  頁面跳轉時傳遞的參數   * @param anim   指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, int[] anim) {    return this.openPage(pageName, bundle, anim, true);  }  /**   * 在當前activity中打開一個fragment,并設置是否添加到返回棧   *   * @param pageName    Fragemnt 名,在page.json中配置。   * @param bundle     頁面跳轉時傳遞的參數   * @param coreAnim    指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @param addToBackStack 是否添加到用戶操作棧中   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack) {    return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), addToBackStack, false);  }  /**   * 打開一個fragment并設置是否新開activity,設置是否添加返回棧   * @param pageName Fragemnt 名,在page.json中配置。   * @param bundle 頁面跳轉時傳遞的參數   * @param coreAnim 指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @param addToBackStack 是否添加到用戶操作棧中   * @param newActivity 該頁面是否新建一個Activity   * @return   */  public final Fragment openPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean addToBackStack, boolean newActivity) {    return this.openPage(pageName, bundle, CoreSwitchBean.convertAnimations(coreAnim), addToBackStack, newActivity);  }  /**   * @param pageName   * @param bundle   * @param coreAnim   * @return   */  public Fragment gotoPage(String pageName, Bundle bundle, CoreAnim coreAnim) {    return this.gotoPage(pageName, bundle, coreAnim,false);  }  /**   * 新建或跳轉到一個頁面(Fragment)。找不到pageName Fragment時,就新建Fragment。找到pageName   * Fragment時,則彈出該Fragement到棧頂上的所有actvity和fragment   *   * @param pageName  Fragemnt 名,在在configure.zip 的pageContext.txt中配置。   * @param bundle   頁面跳轉時傳遞的參數   * @param coreAnim    指定的動畫理性 none/slide(左右平移)/present(由下向上)/fade(fade 動畫)   * @param newActivity 該頁面是否新建一個Activity   * @return   */  public Fragment gotoPage(String pageName, Bundle bundle, CoreAnim coreAnim, boolean newActivity) {    CoreSwitcher pageCoreSwitcher = this.getSwitcher();    if (pageCoreSwitcher != null) {      CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, coreAnim, true, newActivity);      return pageCoreSwitcher.gotoPage(page);    } else {      Log.d(TAG, "pageSwitcher is null");      return null;    }  }  /**   * 打開fragment并請求獲得返回值   * @param pageName   * @param bundle   * @param coreAnim   * @param requestCode 請求碼   * @return   */  public final Fragment openPageForResult(String pageName, Bundle bundle, CoreAnim coreAnim, int requestCode) {    return this.openPageForResult(false, pageName, bundle, coreAnim, requestCode);  }  /**   * 打開fragment并請求獲得返回值,并設置是否在新activity中打開   * @param newActivity   * @param pageName   * @param bundle   * @param coreAnim   * @param requestCode   * @return   */  public final Fragment openPageForResult(boolean newActivity, String pageName, Bundle bundle, CoreAnim coreAnim, int requestCode) {    CoreSwitcher pageCoreSwitcher = this.getSwitcher();    if (pageCoreSwitcher != null) {      CoreSwitchBean page = new CoreSwitchBean(pageName, bundle, coreAnim, true, newActivity);      page.setRequestCode(requestCode);      return pageCoreSwitcher.openPageForResult(page, this);    } else {      Log.d(TAG, "pageSwitcher is null");      return null;    }  }  @Override  public void onAttach(Activity activity) {    super.onAttach(activity);    mActivity = activity;  }  @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    if (getPageName() != null) {      Log.d(TAG, "====Fragment.onCreate====" + getPageName());    }  }  public String getPageName() {    return mPageName;  }  public void setPageName(String pageName) {    mPageName = pageName;  }  @Override  public void onDetach() {    super.onDetach();    mActivity = null;  }  //頁面跳轉接口  public interface OnFragmentFinishListener {    void onFragmentResult(int requestCode, int resultCode, Intent intent);  }}

其實無論BaseActivity還是BaseFragment的原理都是一樣的,都是通過接口中的函數進行切換,最終都是調用了我們前面所說的兩個核心函數。所謂的難點,其實就是openPageForResult的函數。如果調整函數中指定了新開activity,則直接調用startActivityForResult函數進行跳轉,目標Activity中為BaseActivity,傳遞一些參數用于識別。

Intent intent = new Intent(this, BaseActivity.class);intent.putExtra("SwitchBean", page);intent.putExtra("startActivityForResult", "true");

然后再onCreate中獲得intent

 Intent mNewIntent = getIntent(); init(mNewIntent);

調用了init函數,在里面獲得傳遞的兩個參數,如果是startActivityForResult,則對fragment設置回調函數,當我們手動設置了setFragmentResult函數后回調就會被調用,即onFragmentResult函數回調

private void init(Intent mNewIntent) {    try {      CoreSwitchBean page = mNewIntent.getParcelableExtra("SwitchBean");      String startActivityForResult = mNewIntent.getStringExtra("startActivityForResult");      this.mFirstCoreSwitchBean = page;      if (page != null) {        BaseFragment fragment = null;        boolean addToBackStack = page.isAddToBackStack();        String pageName = page.getPageName();        Bundle bundle = page.getBundle();        fragment = (BaseFragment) CorePageManager.getInstance().openPageWithNewFragmentManager(getSupportFragmentManager(), pageName, bundle, null, addToBackStack);        if (fragment != null) {          if ("true".equalsIgnoreCase(startActivityForResult)) {            fragment.setRequestCode(page.getRequestCode());            fragment.setFragmentFinishListener(new BaseFragment.OnFragmentFinishListener() {              @Override              public void onFragmentResult(int requestCode, int resultCode, Intent intent) {                BaseActivity.this.setResult(resultCode, intent);              }            });          }        } else {          this.finish();        }      }    } catch (Exception e) {      e.printStackTrace();      Log.d(TAG, e.getMessage());      this.finish();    }  }

最后的最后,也就是整個Fragment跳轉框架的初始化了,繼承Application編寫一個應用程序類完成初始化。

public class BaseApplication extends Application {  private static LocalBroadcastManager mLocalBroadcatManager;  private static Context mContext;  private static BaseApplication instance;  public static Context getContext() {    return mContext;  }  @Override  public void onCreate() {    super.onCreate();    instance = this;    mContext = this.getApplicationContext();    CorePageManager.getInstance().init(this);  }  /**   * 發送本地廣播退出程序   */  public void exitApp() {    Intent intent = new Intent();    intent.setAction(Config.ACTION_EXIT_APP);    intent.addCategory(Intent.CATEGORY_DEFAULT);    BaseApplication.getLocalBroadcastManager().sendBroadcast(intent);    BaseActivity.unInit();  }  public static LocalBroadcastManager getLocalBroadcastManager() {    if (mLocalBroadcatManager == null) {      mLocalBroadcatManager = LocalBroadcastManager.getInstance(mContext);    }    return mLocalBroadcatManager;  }}

完成聲明

<manifest  package="cn.edu.zafu.corepage"  xmlns:android="http://schemas.android.com/apk/res/android">  <application android:allowBackup="true"         android:label="@string/app_name"    >    <activity      android:name="cn.edu.zafu.corepage.base.BaseActivity"      android:configChanges="keyboardHidden|orientation|screenSize"      android:exported="false"      android:launchMode="standard"      android:screenOrientation="portrait"      android:theme="@style/BaseActivityTheme"      android:windowSoftInputMode="adjustUnspecified|stateHidden" >    </activity>  </application></manifest>

之后的一切就會變得特別簡單,調用即可。由于我是用android studio建的module,因此直接引用該module即可,然后提供一個程序入口Activity,該類繼承BaseActivity,將該Activity聲明在manifest文件中,然后我們再也不用新建Activity了,后續的頁面跳轉全都使用Fragment來完成。并且可以設置動畫類型等一系列的參數。

使用非常簡單

openPage("test1",null, CoreAnim.slide);//打開一個頁面,不傳遞參數第二個傳null,第三個參數為動畫類型,此方法有重載方法,第四個參數表示是否添加到返回棧,第五個參數表示是否新開activity,一般情況下,只需傳遞前三個參數即可,而動畫類型,處理傳遞枚舉類,還支持自定義的動畫,對應的文件參考res/anim目錄下的相應文件openPageForResult("test2",bundle,CoreAnim.fade,requestCode);//打開一個頁面并獲得返回結果,之后調用setFragmentResult和popToBack設置結果 setFragmentResult(500, intent); popToBack();重寫onFragmentResult函數獲取返回結果@Overridepublic void onFragmentResult(int requestCode, int resultCode, Intent data) {}//這個使用過程同startActivityFor的整個過程

效果圖:

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色妞色视频一区二区三区四区| 国产精品免费一区二区三区都可以| 日本中文字幕不卡免费| 亚洲国产精品va在线观看黑人| 亚洲综合视频1区| 亚洲国产精品小视频| 久久久久久噜噜噜久久久精品| 欧美裸体视频网站| 国产91露脸中文字幕在线| 日韩精品视频中文在线观看| 日韩欧美在线观看| 国产免费一区二区三区在线能观看| 国产在线精品一区免费香蕉| 中文字幕欧美日韩va免费视频| 俺也去精品视频在线观看| 亚洲人免费视频| 精品毛片网大全| 国产久一一精品| 亚洲午夜精品视频| 亚洲理论片在线观看| 亚洲天堂av网| 久久久久久久久久久成人| 97人人做人人爱| 91免费的视频在线播放| 久久福利网址导航| 美乳少妇欧美精品| 欧美成人激情视频| 欧美日韩精品在线| 久热在线中文字幕色999舞| 国产精品永久在线| 国产激情999| 国产精品永久在线| 欧美一级片免费在线| 亚洲性夜色噜噜噜7777| 欧美色道久久88综合亚洲精品| 国产精品一区二区久久久| 久久艳片www.17c.com| 高清视频欧美一级| 日韩欧美亚洲国产一区| 国产欧美精品va在线观看| 国产极品jizzhd欧美| 国产在线拍揄自揄视频不卡99| 亚洲一区二区在线| 国产91|九色| 国产女同一区二区| 日韩欧美a级成人黄色| 亚洲成人久久电影| 国产一区深夜福利| 欧美xxxx18国产| 日韩av三级在线观看| 亚洲精品国精品久久99热| 亚洲高清av在线| 视频在线一区二区| 久久99视频精品| 4438全国成人免费| 色综合亚洲精品激情狠狠| 亚洲丝袜在线视频| 欧美资源在线观看| 久久久久久久国产精品| 91在线免费视频| 日韩国产在线播放| 日韩成人av网址| 亚洲美女黄色片| 国产精品久久久久久搜索| 亚洲石原莉奈一区二区在线观看| 一区二区三区四区视频| 日韩av第一页| 日韩日本欧美亚洲| 尤物yw午夜国产精品视频明星| xxxx性欧美| 久久影视电视剧免费网站清宫辞电视| 亚洲伦理中文字幕| 91嫩草在线视频| 久久久久久久久久久av| 欧美日韩精品中文字幕| 中文字幕v亚洲ⅴv天堂| 亚洲伊人一本大道中文字幕| 久久精品国产久精国产一老狼| 中文字幕日韩综合av| 成人www视频在线观看| 亚洲午夜av电影| 91精品国产综合久久久久久久久| 国产婷婷97碰碰久久人人蜜臀| 国产成人一区三区| 81精品国产乱码久久久久久| 国产亚洲精品激情久久| 久久视频在线看| 黄色一区二区在线观看| 日韩中文字幕视频| 欧美性猛交xxxx乱大交极品| 欧美专区在线视频| 亚洲国产一区二区三区在线观看| 一区二区三区动漫| 欧美高跟鞋交xxxxxhd| 日韩精品久久久久久久玫瑰园| 日韩成人免费视频| 国产精品视频99| 国产精品久久久久久av下载红粉| 精品久久久一区二区| 久久精品国产视频| 中文字幕日韩精品有码视频| 国产91免费看片| 欧美日韩午夜视频在线观看| 国产91在线视频| 亚洲福利视频专区| 日韩在线观看免费av| 国模极品一区二区三区| 欧美精品成人在线| 欧美在线xxx| 国产精品香蕉国产| 国产国语刺激对白av不卡| 午夜精品国产精品大乳美女| 欧美交受高潮1| 欧美日韩国产页| 97视频在线观看播放| 欧美亚洲视频一区二区| 91视频国产精品| 深夜精品寂寞黄网站在线观看| 日韩黄色在线免费观看| 日韩欧美aⅴ综合网站发布| 欧美亚洲视频一区二区| 美日韩丰满少妇在线观看| 亚洲黄色www网站| 日韩av电影手机在线观看| 欧美一级片久久久久久久| 日本最新高清不卡中文字幕| 国产精品99久久久久久人| 91国内产香蕉| 日韩在线一区二区三区免费视频| 日韩a**站在线观看| 亚洲跨种族黑人xxx| 国产+成+人+亚洲欧洲| 亚洲sss综合天堂久久| 26uuu国产精品视频| 亚洲一区免费网站| 日韩精品极品在线观看播放免费视频| 在线电影中文日韩| 中文字幕日韩视频| 国产丝袜一区二区三区| 国产视频精品免费播放| 久久精品国产99国产精品澳门| 亚洲大胆人体在线| 97久久精品在线| 国产精品久久久久久久久男| 亚洲人a成www在线影院| 亚洲第一精品福利| 国内精品美女av在线播放| 精品在线观看国产| 欧美激情视频播放| 久久久久久91香蕉国产| 91免费人成网站在线观看18| 精品国产乱码久久久久酒店| 中文字幕在线日韩| 中文字幕在线看视频国产欧美在线看完整| 亚州欧美日韩中文视频| 国产亚洲综合久久| 免费成人高清视频| 狠狠躁夜夜躁人人躁婷婷91| 日韩在线资源网| 成人久久久久爱| 国产精品久久久久秋霞鲁丝| 久久久久久久久久久久久久久久久久av| 国产精品aaa| 97视频在线观看免费高清完整版在线观看|