Fragment 一经推出,就广泛的使用在项目中,在适配方面,减少代码冗余方面大有助益,那么Fragment和Activity如何交互呢,我所知的有,通过fragment.setxxx(),((类型转换)getActivity).setxxx(),eventbus等等,那么是否可以通过回调让Activity和 Fragment及时交互呢?
首先讲一下我对回调的理解,A要完成某件事情,但是他没法完成,需要委托B去完成,B完成了告诉A完成的情况。
举一个列子,在办理银行卡的时候,有时候会开通短信服务,当你的银行卡中钱发生变化的时候 就会及时通知你,这就相当会 客户给银行设置了一个监听,这个监听一直在等待,钱有变化了 就回调出结果,如果你不设置监听,钱变化了,自然也不会及时通知你
写一个简单的例子:
MoneyCallBack 作为一个接口,主要用于监听银行卡中钱的变化,相当于定制的短信服务
package callbackDemo;
/**
* @author why 小二
* 短信业务
*
*/
public interface MoneyCallBack {
void savaMoney();//短信通知用户存钱了
void spendMoney();//短信通知用户消费了
}
Bank 作为一个银行类主要用于处理存钱,取钱 啥啥啥的金融业务,当用户的钱发生 变化时,如果用户办理了短信服务,通知用户钱发生了变化,这里的短信服务相当于上面的MoneyCallBack,如果不设置,当然也就不通知了
package callbackDemo;
/**
* @author why
* 银行
*
*/
public class Bank {
MoneyCallBack mCallBack;
int mMonthCount=12;// 办理短信服务的月数,一般为12个月
public void setCallBack(MoneyCallBack mCallBack) {
this.mCallBack = mCallBack;
}
public void getMoney(){
new Thread(){public void run() {
for (int i = 0; i < mMonthCount; i++) {
if (mCallBack!=null) {
mCallBack.savaMoney();
mCallBack.spendMoney();
}
}
};
}.start();
}
}
Client作为 办理银行业务的自由人,可以办理任何业务
package callbackDemo;
/**
* @author why 小二
* 客户
*
*/
public class Client {
public static void main(String[] args) {
Bank bank=new Bank();
//定制短信服务
bank.setCallBack(new MoneyCallBack() {
@Override
public void spendMoney() {
System.out.println("尊敬的客户,你存入了钱");
}
@Override
public void savaMoney() {
System.out.println("尊敬的客户,你消费了钱");
}
});
bank.getMoney();
}
}
好了,现在执行下 程序,12个月中有存钱,有消费
如果你想知道 消费 收入的具体变化,只需在回调接口中返回具体的数目,把接口稍作修改
package callbackDemo;
/**
* @author why 小二
* 短信业务
*
*/
public interface MoneyCallBack {
void savaMoney(String money);//短信通知用户存钱了
void spendMoney(String money);//短信通知用户消费了
}
总之回调很简单,你可以通过任何方式给B设计监听,构造函数,set等等,只要设置了,B就可以通过接口返回,现在通过一个 Activity和 Fragment的例子讲解,写一个非常简单的,Fragment中是一个城市列表,用于选择一个城市,Activity 用大标题显示出来当前选择的城市是哪个城市,adapter点击发生变化了通过 回调返回给Fragment,Fragment 再回调给 Activity
先看下效果
右边的单选是随意找的两张图片,有点丑,效果是非常好的,但是我录制的不好就这个丑样子了
现在贴代码
先看下 Activity 布局 ,只有一个TextView 和LinearLayout ,用于展示当前城市的名字 和 添加Fragment。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_content"></LinearLayout>
</LinearLayout>
Activity 代码
package com.example.why.callbackinteraction;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.TextView;
/**
* Created by why on 2015/9/6.
*/
public class MainActivity extends Activity {
private TextView mTitleView;
private FragmentManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitleView= (TextView) findViewById(R.id.title);
mTitleView.setText("你当前选择的城市是 ");
manager=getFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
CityChoiceFragment fragment=new CityChoiceFragment();
//Fragment 实例化 之后设置,设置了 ,Fragment 选择城市发生改变返回给 Activity
fragment.setmFragmentCallBack(new CityChoiceFragment.FragmentCallBack() {
@Override
public void getCity(String cityName) {
mTitleView.setText(String.format("你当前选择的城市是 %s",cityName));
}
});
transaction.add(R.id.fragment_content,fragment);
transaction.commitAllowingStateLoss();
}
}
很简单,我就不解释了,下面是 Fragment 和 Adapter的代码,布局很简单,不上了,代码不解释了,代码中有注释
package com.example.why.callbackinteraction;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by why on 2015/9/5.
*/
public class CityChoiceFragment extends Fragment {
private ListView mCityListView;
private List<String> mCitys; //城市列表
CityAdapter mAdapter;
public void setmFragmentCallBack(FragmentCallBack mFragmentCallBack) {
this.mFragmentCallBack = mFragmentCallBack;
}
<span style="white-space:pre"> </span>
private FragmentCallBack mFragmentCallBack;//用于把内容回调给Activity
interface FragmentCallBack{
void getCity(String cityName);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_city_choice,null);
initDate();
initView(view);
return view;
}
/**
* @param view
*/
private void initView(View view) {
mCityListView= (ListView) view.findViewById(R.id.city_list);
mAdapter=new CityAdapter(mCitys,getActivity());
// 为adapter设置接口,如果设置了,adapter有所改变 ,将会把改变的的城市返回,接口可以在实例化或实例化后位置设置,
mAdapter.setmChoiceChangeCallBack(new CityAdapter.ChoiceChangeCallBack() {
@Override
public void getSelectCity(String cityName) {
if (mFragmentCallBack!=null){
mFragmentCallBack.getCity(cityName);
}
}
});
mCityListView.setAdapter(mAdapter);
}
/**
* 初始化数据
*/
private void initDate() {
mCitys=new ArrayList<>();
mCitys.add("博乐");
mCitys.add("伊宁");
mCitys.add("阿拉山口");
mCitys.add("霍尔果斯");
mCitys.add("奎屯");
mCitys.add("石河子");
mCitys.add("乌鲁木齐");
mCitys.add("哈密");
mCitys.add("吐鲁番");
mCitys.add("库尔勒");
mCitys.add("鄯善");
mCitys.add("北屯");
mCitys.add("和田");
mCitys.add("昌吉");
mCitys.add("塔城");
mCitys.add("克拉玛依");
mCitys.add("阿图什");
mCitys.add("阿克苏");
}
}
class CityAdapter extends BaseAdapter{
interface ChoiceChangeCallBack{
void getSelectCity(String cityName);
}
public void setmChoiceChangeCallBack(ChoiceChangeCallBack mChoiceChangeCallBack) {
this.mChoiceChangeCallBack = mChoiceChangeCallBack;
}
private ChoiceChangeCallBack mChoiceChangeCallBack; //当前点击item的回调接口,如果点击了,通过接口把选择的城市返回给 fragment
private List<String> mCitys;
private Context mContext;
private LayoutInflater mInflater;
private String mCurrentCity="";
CityAdapter(List<String> mCitys, Context mContext) {
this.mCitys = mCitys;
this.mContext = mContext;
mInflater=LayoutInflater.from(mContext);
}
@Override
public int getCount() {
return mCitys==null?0:mCitys.size();
}
@Override
public Object getItem(int position) {
return mCitys==null?null:mCitys.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHodler hodler;
if (convertView==null){
hodler=new ViewHodler();
convertView=mInflater.inflate(R.layout.adapter_city_choice,null);
hodler.name= (TextView) convertView.findViewById(R.id.name);
hodler.choice= (TextView) convertView.findViewById(R.id.choice);
convertView.setTag(hodler);
}else{
hodler= (ViewHodler) convertView.getTag();
}
hodler.name.setText(mCitys.get(position));
hodler.choice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentCity=mCitys.get(position);
v.setBackgroundResource(R.drawable.sure);
if (mChoiceChangeCallBack!=null){
mChoiceChangeCallBack.getSelectCity(mCurrentCity);
}
notifyDataSetChanged();
}
});
if (mCurrentCity.equals(mCitys.get(position))){
hodler.choice.setBackgroundResource(R.drawable.sure);
}else {
hodler.choice.setBackgroundResource(R.drawable.add);
}
return convertView;
}
class ViewHodler{
TextView name;
TextView choice;
}
}
module下载地址 ,请点击 这里