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

本文探讨了在Android开发中Fragment与Fragment、Fragment与Activity之间的通信方式,从野路子做法(直接调用)到正规军做法(使用接口)。通过具体的实现过程,展示了如何通过接口实现解耦,降低Fragment间的耦合度,以提高代码的可复用性和遵循面向对象编程思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    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;
	
	@Override
	public 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 {

	@Override
	public 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() {

			@Override
			public 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{

	@Override
	protected 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);
	}

	@Override
	public void onItemClick(int position) {
		setNewsTitle(position);
	}
}


TitleFragment.java
public class TitleFragment extends ListFragment {

	@Override
	public 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() {

			@Override
			public 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 {

	@Override
	public 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() {

			@Override
			public 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{

	@Override
	protected 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);
	}

	@Override
	public void onItemClick(int position) {
		setNewsTitle(position);
	}
}


至此,耦合完全解除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值