接口实现Fragment、Activity间互调解耦

来源:互联网 发布:axure mac 团队协作 编辑:程序博客网 时间:2024/06/05 16:47

    fragment之间及Fragment与Activity互调在实际应用中极为常见,比如官方API介绍Fragment给出的平板新闻客户端例子,UI左边是标题Fragment,UI右边是内容Fragment,点击不同的标题,显示不同的新闻内容,这是一个简单的Fragment间互调。根据Fragment互调是否解耦,是否贯彻面向对象编程思想,可以分为野路子做法及正规军做法,当然二者都能实现目的。本文通过具体的实现及改进过程,逐步降低Fragment互调的耦合度。


一、野路子用法

1、Fragment/Activity---调用--->Fragment

    每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag(),或者findFragmentById()获得任何Fragment实例,然后进行操作。

2、Fragment--调用-->Activity

    通过getActivity得到当前绑定的Activity的实例,然后进行操作。

    上面两种编程思想一目了然,在编程中也极为常见,具体到新闻客户端例子,就是在TitleFragment中通过代码直接调用ContentFragment,这样做TitleFragment就与ContentFragment高度耦合,TitleFragment代码被写死,直接破坏Fragment的重用思想。

    下面是应用传统野路子实现过程:

ContentFragment.java

public class ContentFragment extends Fragment {String[] news = new String[]{"日企员工如何跟老板请假9.3日","手撕鬼子","9月9日忆山东兄弟",};private int dataId;private TextView tv;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {tv = new TextView(getActivity());Bundle bundle = getArguments();dataId = bundle.getInt("dataId");tv.setText(news[dataId]);return tv;}public void setData(int dataId){this.dataId = dataId;tv.setText(news[dataId]);}}

TitleFragment.java
public class TitleFragment extends ListFragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);//初始化数据ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, data);setListAdapter(adapter);fm = getFragmentManager();getListView().setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {//显示contentFragment//传数据给ContentFragment,修改那边的结果f = fm.findFragmentByTag("content");if(f == null){//先创建ContentFragment,然后添加到布局里面。FragmentTransaction ft = fm.beginTransaction();f = new ContentFragment();//给fragment如何赋初始值Bundle bundle = new Bundle();bundle.putInt("dataId",0);f.setArguments(bundle);ft.add(R.id.fg_content, f, "content");ft.commit();}else{ContentFragment cf = (ContentFragment) f;                                        f.getArguments().putInt("dataId",position);//获取bundle}}


二、正规军用法:

    Fragment互调使用接口通讯。考虑Fragment的重用,所以必须降低Fragment与Activity的耦合,而且Fragment更不应该直接操作别的Fragment,毕竟Fragment操作应该由它的管理者Activity来决定。

    改进一:

TitleItemClickListener.java
public interface TitleItemClickListener {void onItemClick(int position );}
</pre><pre code_snippet_id="1587149" snippet_file_name="blog_20160224_7_886404" name="code" class="html">MainActivity.java
public class MainActivity extends Activity implements TitleItemClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FragmentManager fm = getFragmentManager();TitleFragment tf = (TitleFragment) fm.findFragmentById(R.id.fg_title);}public void setNewsTitle(int  position){TextView tv = (TextView) findViewById(R.id.tv);tv.setText("鬼子"+position);}@Overridepublic void onItemClick(int position) {setNewsTitle(position);}}

TitleFragment.java
public class TitleFragment extends ListFragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);//初始化数据ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, data);setListAdapter(adapter);fm = getFragmentManager();getListView().setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {TitleItemClickListener listener = (TitleItemClickListener) getActivity();listener.onItemClick(position);}}


Fragment之间通过Activity通讯,降低了耦合性,但TitleFragment的重用性有待加强,因为TitleFragment的代码:
TitleItemClickListener listener = (TitleItemClickListener) getActivity();
这段代码涉及到getActivity(),所以只能被Activity重用,这是一个限制,所以可以进一步改进。


改进二:

TitleFragment.java
public class TitleFragment extends ListFragment {@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);//初始化数据ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, data);setListAdapter(adapter);fm = getFragmentManager();getListView().setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {listener.onItemClick(position);}public void setTitleItemClickListener(TitleItemClickListener listener){this.listener = listener;}}

MainActivity.java
public class MainActivity extends Activity implements TitleItemClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FragmentManager fm = getFragmentManager();TitleFragment tf = (TitleFragment) fm.findFragmentById(R.id.fg_title);tf.setTitleItemClickListener(this);}public void setNewsTitle(int  position){TextView tv = (TextView) findViewById(R.id.tv);tv.setText("鬼子"+position);}@Overridepublic void onItemClick(int position) {setNewsTitle(position);}}


至此,耦合完全解除。
0 0