2017-07-30 84 views
0

看來,只要您在支持片段管理器的事務中使用.replace()方法,就會重新創建ViewModel。這是故意的嗎?片段實例本身沒有改變,ViewModel將在旋轉/配置更改期間(部分)保留。支持片段管理器.replace()和ViewModel

我看到以下場景:

  1. 獲取視圖模型REF(計數= 0),更新計數= 1,旋轉數= 1,所謂的onCreate再次數= 0(查看模型重新創建)。
  2. 調用.replace()並重新創建視圖模型(活動和片段實例不變)。

使用支持庫26.0.0。

ViewModel在我的片段onCreate創建並可以被限制在Fragment

viewModel = ViewModelProviders.of(this).get(DashboardViewModel::class.java) 

任何闡明,如果這是正常的一些輕?

+0

「片段實例本身不是CH老化「 - 這是什麼意思?一個'ViewModel'被實現爲你傳入'ViewModelProviders.of()'的任何'FragmentActivity'或'Fragment'的子保留片段。 – CommonsWare

+0

在活動我有一個片段陣列和我只是片段之間交換所述陣列中(使用底部NAV): '片段= mapOf(id來片段等)' 再後來: ' supportFragmentManager.beginTransaction()。replace(R.id.fragmentContainer,fragment).commit()' 我可以看到片段引用是相同的(未被重新創建)。 – Luke

+0

如果我移動到活動範圍,它可以正常工作。 'viewModel = ViewModelProviders.of(activity).get(DashboardViewModel :: class.java)' – Luke

回答

1

replace()當你製作不同的片段時,會被調用來調用。對於您撥打update()的同一個片段。

replace()方法意味着你可以用不同的佈局(物理結構)不同的東西替換你當前的片段。你甚至不能保證它從前一個片段使用的內存開始。 ViewModel是整個容器的一種佈局。因此,對於具有不同物理結構的對象(可能具有不同的內存 - 我正在編寫可能是,因爲您可以用相同的片段進行替換),則必須重新創建不同的ViewModel,定義它的容器。這是因爲一個ViewModel對象指向一個引用容器,下次你有不同的片段時,由ViewModel定義的片段容器位於其他位置,因此您需要另一個ViewModel對象指向該片段容器。

但是,當你做update()rotate(),你保證更新片段的內存空間可以減少/增加,但它仍然是開始的內存保持不變。所以不需要創建ViewModel。這是因爲舊的ViewModel對象正在引用同一個舊的Fragment容器。

當你做create()時,它創建GUI的一切,所以很明顯,這裏再次發生ViewModel創建。

跟蹤ViewModelcount是基於上面的說明。

ViewModel正在我的片段的onCreate中創建,並被限制爲片段。這是片段的權力代表團。

1

至於@CommonsWare提到的viewmodel裏的fragment裏面的實例應該和Activity一樣。

因此,活動裏面,你應該做這樣的事情

MyViewModel vm = ViewModelProviders.of(this).get(MyViewModel.class);

的片段裏,你應該做這樣的事情

MyViewModel vm = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

在結果,他們會用同一個實例。

但是,如果您嘗試使用它的片段裏面

MyViewModel vm = ViewModelProviders.of(this).get(MyViewModel.class);

視圖模型將在該片段中,當你旋轉設備重建。 由於實例保存在片段內部而不是活動,當重新創建活動時,片段也將被重新創建,並且MyViewModel實例也會被重新創建。

嘗試採取的例子來看看在主詳細片段(這可能很容易解決您的問題)ViewModel in Android Developer

public class MasterFragment extends Fragment { 
    private SharedViewModel model; 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); 
     itemSelector.setOnClickListener(item -> { 
      model.select(item); 
     }); 
    } 
} 

public class DetailFragment extends LifecycleFragment { 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); 
     model.getSelected().observe(this, { item -> 
      // update UI 
     }); 
    } 
} 

我也曾在github上做了簡單的主從模板

SimpleDetailActivity.java

SimpleDetailFragment.java