Android Architecture Componets - ViewModel

ViewModel

/**
ViewModel是一個(gè)負(fù)責(zé)準(zhǔn)備和管理Activity或Fragment數(shù)據(jù)的類。
它還處理Activity / Fragment與其他應(yīng)用程序的通信 (例如調(diào)用業(yè)務(wù)邏輯類)
ViewModel會(huì)在一個(gè)關(guān)聯(lián)的范圍內(nèi)(activity 或者 fragment)創(chuàng)建,只要activity或fragment是活著的,它將被保留.
換句話說(shuō),這意味著如果它的所有者由于配置改變被銷毀了(例如旋轉(zhuǎn)), ViewModel不會(huì)被銷毀,所有者的新實(shí)例將重新連接到現(xiàn)有的ViewModel。
ViewModel的目的是獲取并保存Activity或Fragment所需的信息. Activity或Fragment應(yīng)該能夠觀察ViewModel中的變化。ViewModel通常通過(guò)LiveData或Android DataBinding公開這些信息。 你也可以使用你喜歡的框架的任何可觀察性構(gòu)造。
ViewModel唯一的職責(zé)就是管理用戶界面的數(shù)據(jù), 它不應(yīng)該訪問您的視圖層次結(jié)構(gòu)或持有引用回到Activity或Fragment.

典型的用法:
 * public class UserActivity extends Activity {
 *
 *     {@literal @}Override
 *     protected void onCreate(Bundle savedInstanceState) {
 *         super.onCreate(savedInstanceState);
 *         setContentView(R.layout.user_activity_layout);
 *         final UserModel viewModel = ViewModelProviders.of(this).get(UserModel.class);
 *         viewModel.userLiveData.observer(this, new Observer<User>() {
 *            {@literal @}Override
 *             public void onChanged(@Nullable User data) {
 *                 // update ui.
 *             }
 *         });
 *         findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
 *             {@literal @}Override
 *             public void onClick(View v) {
 *                  viewModel.doAction();
 *             }
 *         });
 *     }
 * }
 
 ViewModel:
  * public class UserModel extends ViewModel {
 *     public final LiveData&lt;User&gt; userLiveData = new LiveData<>();
 *
 *     public UserModel() {
 *         // trigger user load.
 *     }
 *
 *     void doAction() {
 *         // depending on the action, do necessary business logic calls and update the
 *         // userLiveData.
 *     }
 * }
ViewModels也可以用作Activity中的不同F(xiàn)ragment之間的通信層。 每個(gè)Fragment可以通過(guò)他們的Activity使用相同的密鑰來(lái)獲取ViewModel。這允許Fragment之間以分離的方式進(jìn)行通信,使得它們不需要直接與另一個(gè)Fragment進(jìn)行通信。
 * public class MyFragment extends Fragment {
 *     public void onStart() {
 *         UserModel userModel = ViewModelProviders.of(getActivity()).get(UserModel.class);
 *     }
 * }
*/
public abstract class ViewModel {
    /**
     * 這個(gè)ViewModel被銷毀時(shí)調(diào)用
     * <p>
     * It is useful when ViewModel observes some data and you need to clear this subscription to
     * prevent a leak of this ViewModel.
     */
    @SuppressWarnings("WeakerAccess")
    protected void onCleared() {
    }
}
ViewModelProviders.of(this).get(MyViewModel::class.java)
// ViewModelProviders
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
    // 確保單例對(duì)象 sDefaultFactory 實(shí)例存在
    initializeFactoryIfNeeded(checkApplication(activity));
    return new ViewModelProvider(ViewModelStores.of(activity), sDefaultFactory);
}
// ViewModelStores
@MainThread
public static ViewModelStore of(@NonNull FragmentActivity activity) {
    // 創(chuàng)建HolderFragment 并且添加到Activity當(dāng)中, 返回ViewModelStore
    return HolderFragment.holderFragmentFor(activity).getViewModelStore();
}
// HolderFragment

// getViewModelStore() 返回該實(shí)例
private ViewModelStore mViewModelStore = new ViewModelStore();

private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager();

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static HolderFragment holderFragmentFor(FragmentActivity activity) {
    return sHolderFragmentManager.holderFragmentFor(activity);
}

// HolderFragmentManager
HolderFragment holderFragmentFor(FragmentActivity activity) {
    FragmentManager fm = activity.getSupportFragmentManager();
    // 根據(jù) HOLDER_TAG 尋找 HolderFragment
    HolderFragment holder = findHolderFragment(fm);
    if (holder != null) {
        return holder;
    }
    // mNotCommittedActivityHolders 保存已經(jīng)執(zhí)行了add操作, 但是沒有添加進(jìn)去的 Fragment
    holder = mNotCommittedActivityHolders.get(activity);
    if (holder != null) {
        return holder;
    }

    if (!mActivityCallbacksIsAdded) {
        mActivityCallbacksIsAdded = true;
        // 在activity的 onDestroy()方法中 mNotCommittedActivityHolders釋放引用
        activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
    }
    // 創(chuàng)建 HolderFragment 添加到當(dāng)前 Activity 當(dāng)中
    holder = createHolderFragment(fm);
    // 上面方法執(zhí)行了 fragment 的 add以及commit 操作, 到HolderFragment 真正添加到activity之前記錄
    mNotCommittedActivityHolders.put(activity, holder);
    return holder;
}
// HolderFragment
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sHolderFragmentManager.holderFragmentCreated(this);
}
// HolderFragmentManager
void holderFragmentCreated(Fragment holderFragment) {
    // 如果是在Fragment中嵌套Fragment, 該返回不為空, 這里只討論Activity的情況
    Fragment parentFragment = holderFragment.getParentFragment();
    if (parentFragment != null) {
        mNotCommittedFragmentHolders.remove(parentFragment);
        parentFragment.getFragmentManager().unregisterFragmentLifecycleCallbacks(
                mParentDestroyedCallback);
    } else {
        // 執(zhí)行 onCreate() 說(shuō)明HolderFragment以及添加到Activity, 可以釋放引用了
        mNotCommittedActivityHolders.remove(holderFragment.getActivity());
    }
}
@NonNull
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
    String canonicalName = modelClass.getCanonicalName();
    if (canonicalName == null) {
        throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
    }
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = mViewModelStore.get(key);

    if (modelClass.isInstance(viewModel)) {
        //noinspection unchecked
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    // 根據(jù)反射創(chuàng)建實(shí)例
    viewModel = mFactory.create(modelClass);
    // 存入 viewModel實(shí)例
    mViewModelStore.put(key, viewModel);
    //noinspection unchecked
    return (T) viewModel;
}

到這里會(huì)發(fā)現(xiàn)只是將一個(gè)毫不起眼的HolderFragment添加到Activity,并且利用HolderFragment中的ViewModelStore中的Map保存了 自定義ViewModel實(shí)例.

HolderFragment是如何在在Activity配置變更被銷毀時(shí)繼續(xù)持有viewModel的?

// HolderFragment
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 這行代碼上面已經(jīng)分析過(guò)了
    sHolderFragmentManager.holderFragmentCreated(this);
}
@Override
public void onDestroy() {
    super.onDestroy();
    // 調(diào)用ViewModel的
    mViewModelStore.clear();
}

// ViewModelStore
public final void clear() {
    for (ViewModel vm : mMap.values()) {
        // 空方法, 繼承給開發(fā)者用, 做釋放等操作
        vm.onCleared();
    }
    // 清空map, 也就是 釋放ViewModel數(shù)據(jù)
    mMap.clear();
}

上面也并沒有什么特殊的操作, 并且在onDestroy() 中釋放了 viewModel, 那么在 Activity例如旋轉(zhuǎn)的時(shí)候會(huì)調(diào)用onDestroy(), 跟著 Fragment的 onDestroyView(), onDestroy(), onDetach() 會(huì)依次觸發(fā). HolderFragment為什么不會(huì)調(diào)用 onDestroy()?

關(guān)鍵來(lái)了!!

// 關(guān)鍵就在 HolderFragment的構(gòu)造方法中
public HolderFragment() {
    setRetainInstance(true);
}
// Fragment
/**
 控制是否在重新創(chuàng)建Activity(例如配置更改)中保留Fragment實(shí)例。這只能用于不在back stack中的Fragment。 如果設(shè)置,則在 recreate Activity時(shí),F(xiàn)ragment生命周期將略有不同:
 onDestroy() 將不會(huì)被調(diào)用 (但onDetach() 仍然會(huì),因?yàn)槠握趶乃?dāng)前的活動(dòng)分離). onCreate(Bundle)將不會(huì)被調(diào)用,因?yàn)槠尾槐恢匦聞?chuàng)建。onAttach(Activity) 和 onActivityCreated(Bundle)仍然被調(diào)用。
 */
public void setRetainInstance(boolean retain) {
    mRetainInstance = retain;
}

所以在ViewModel類的注釋中有一段

ViewModel唯一的職責(zé)就是管理用戶界面的數(shù)據(jù), 它不應(yīng)該訪問您的視圖層次結(jié)構(gòu)或持有引用回到Activity或Fragment.

一旦ViewModel持有了Activity, 并且在旋轉(zhuǎn)時(shí), 新的Activity需要?jiǎng)?chuàng)建, 而舊的Activity需要被釋放. 但是被ViewModel持有而釋放不了就有可能造成內(nèi)存泄漏.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容