Fragment與Activity。什么時候用什么時候不用?
回答: 看需求!
個人覺得推薦場景:
(使用Fragment完全替換Activity,而Activity用來管理Fragment或者把fragment當(dāng)作一個輕量級activity使用)
當(dāng)你一個Activity需要模塊化的時候,你可以單獨(dú)寫一個Fragment并且嵌套在任何一個界面,不用擔(dān)心重復(fù)代碼。
一般主頁的每個tab都是用Fragment,類似的一個頁面下有多個布局需要切換的時候感覺用Fragment很方便
布局在不同的設(shè)備上比如手機(jī)和平板上的適配
比如 App 中有一個新用戶注冊功能,包括設(shè)置用戶名、密碼、手機(jī)號等等流程,設(shè)計師在 UI 設(shè)計上將每個流程單獨(dú)設(shè)計成一個界面,引導(dǎo)用戶一步步操作。作為開發(fā)人員,如果將每一個完善信息的流程單獨(dú)設(shè)置成一個 Activity 的話操作起來就比較繁瑣,并且也不易于應(yīng)用里的邏輯處理,而如果使用 Fragment 并結(jié)合回退棧的話,就非常合適了
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.hide(firstStepFragment);
if (secondStepFragment==null){
ft.add(R.id.fl_content, secondStepFragment);
}else {
ft.show(secondStepFragment);
}
ft.addToBackStack(null);
ft.commit();
注意:這里使用了 hide() 方法,而不是 replace() 方法,因為我們當(dāng)然希望用戶返回上一步操作時,之前設(shè)置的內(nèi)容不會消失。
Activity管理Fragment的思路:(曾經(jīng)用過)
當(dāng)然別忘了FragmentManager。管理著 正在activity里顯示的fragment們(用list)以及detach之后跟view hiearchy斷開聯(lián)系的被放進(jìn)backstack的fragment:
建一個hashmap,用于存放已實例過的fragment,要復(fù)用的時候直接拿出來,而且還可以解決Fragment 重疊問題;
-
寫一個Basefragment,子Fragment繼承與它,自定義接口,在activity里實現(xiàn)接口方法,因此activity可以根據(jù)待實例化fragment的屬性進(jìn)行管理控制。(這也是觀察著模式)
具體實現(xiàn)方式如下:
public class BaseFragment extends Fragment implements View.OnClickListener{
public interface IOneFragmentClickListener{
void onOneFragmentClick();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.fragment_one, null);
contentView.findViewById(R.id.edt_one).setOnClickListener(this);
return contentView;
}
@Override
public void onClick(View v) {
if (getActivity() instanceof IOneFragmentClickListener){
((IOneFragmentClickListener) getActivity()).onOneFragmentClick();
}
}
}
只要在宿主 Activity 實現(xiàn) Fragment 定義的對外接口 IOneFragmentClickListener,便可以實現(xiàn) Fragment 調(diào)用 Activity 的功能。
fragment的使用:
作為 Activity 界面的一部分,F(xiàn)ragment 的存在必須依附于 Activity,并且與 Activity 一樣,擁有自己的生命周期,同時處理用戶的交互動作。同一個 Activity 可以有一個或多個 Fragment 作為界面內(nèi)容,并且可以動態(tài)添加、刪除 Fragment,靈活控制 UI 內(nèi)容,也可以用來解決部分屏幕適配問題。
另外,support v4 包中也提供了 Fragment,兼容 Android 3.0 之前的系統(tǒng)(當(dāng)然,現(xiàn)在 3.0 之前的系統(tǒng)在市場上已經(jīng)很少見了,可以不予考慮),使用兼容包需要注意兩點:
Activity 必須繼承自 FragmentActivity;
使用 getSupportFragmentManager() 方法獲取 FragmentManager 對象;
fragment 生命周期:
一邊看一邊提出一些問題:
- attach跟add怎么理解?inflate呢?
- attach有什么作用?有什么好處,因此適合什么場景?
個人對提出問題的回復(fù):
Applications should generally not implement a constructor. Prefer
{@link #onAttach(Context)} instead. It is the first place application code can run where
the fragment is ready to be used - the point where the fragment is actually associated with its context. Some applications may also want to implement {@link #onInflate} to retrieve
attributes from a layout resource, although note this happens when the fragment is attached.</pre>
- attach:將fragment與Activirty聯(lián)系起來,通過context。所以通過fragment startActiviotyForResult 其實也是Activity start的,回調(diào)onActivityResult() 也是應(yīng)該由activity處理。 </pre>
- add:將fragment加到ViewHiearchy中,通過把fragment加到manager管理的active的fragment的List里。
- onInflate():保存布局里的屬性
Called when a fragment is being created as part of a view layout
inflation, typically from setting the content view of an activity. This may be called immediately after the fragment is created from a <fragment>
tag in a layout file. Note this is <em>before</em> the fragment's
{@link #onAttach(Activity)} has been called; all you should do here is
parse the attributes and save them away. <p>This is called every time the fragment is inflated, even if it is
being inflated into a new instance with saved state. It typically makes sense to re-parse the parameters each time, to allow them to change with different configurations.</p> </pre>
attach與detach及回退棧的配合,如果當(dāng)你detach fragment時,那么被移除的fragment就被停止了(沒有消亡,但視圖已經(jīng)銷毀了),如果用戶導(dǎo)航回來重新加載這個fragment,它將會重新啟動,視圖也會重新創(chuàng)建,如果你沒有把事務(wù)加入到堆棧中,當(dāng)fragment被remove時,這個fragment也就消亡了。
通信方式
通常,F(xiàn)ragment 與 Activity 通信存在三種情形:
-
Activity 操作內(nèi)嵌的 Fragment
由于 Activity 持有所有內(nèi)嵌的 Fragment 對象實例(創(chuàng)建實例時保存的 Fragment 對象,或者通過 FragmentManager 類提 供的 findFragmentById() 和 findFragmentByTag() 方法也能獲取到 Fragment 對象),所以可以直接操作 Fragment;
Fragment 操作宿主 Activity;
Fragment 通過getActivity()
方法可以獲取到宿主 Activity 對象(強(qiáng)制轉(zhuǎn)換類型即可),進(jìn)而可以操作宿主 Activity;那么很自然的,獲取到宿主 Activity 對象的 Fragment 便可以操作其他 Fragment 對象。Fragment 操作同屬 Activity中的其他 Fragment。
高內(nèi)聚,低耦合。Fragment 做好自己的事情即可,所有涉及到 Fragment 之間的控制顯示等操作,都應(yīng)交由宿主 Activity來統(tǒng)一管理。