回调函数API

http://www.ituring.com.cn/article/131447

回调函数

把回调和API(Application Programming Interface,应用程序编程接口)放在一起理解 enter image description here

API:低层将函数封装起来供给高层来调用。一般来说这些函数对高层来说都是已知的。
回调:回调正好相反,它是高层提供给低层的调用,对于低层来说高层的函数是未知的。

其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层的那个函数。

例如:模块A有一个函数foo,它向模块B传递foo的地址,然后B里面发生某种事件时,通过A里面传递过来的foo的地址来调用foo函数,通知A发生了什么事情,让A做出反应。这样我们就称foo为回调函数。

为了和最后一张图保持一致,故意倒过来了! ^^

理解CriminalIntent中关于回调的例子 (P324)

要想实现的目的是:向crime的明细fragment中添加CrimeFragment。让CrimeListActivity可以展示一个完整的双版面的用户界面。

enter image description here[+]查看原图

我们可能首先想到这么做:为平板设备实现一个CrimeListFragment。onListItemClick(…)监听器方法。这样onListItemClick(…)方法会获取CrimeListActivity中的FragmentManager,然后提交一个fragment事务,将CrimeFragment添加到明细fragment容器中。

public void onListItemClick(ListView l, View v, int position, long id){
Crime crime = ((CrimeAdapter)getListAdapter()).getItem(position);
Fragment fragment = CrimeFragment.newInstance(crime.getId());
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.beginTransaction().add(R.id.detailFragmentContainer, fragment).commit();
}
如果要开发一个fragment来添加其他fragment到activity的FragmentManager,那么这个fragment就必须知道托管的activity是如何工作的。这样就破坏了fragment的独立性。 下面采用另外一种做法:

添加回调接口(CrimeListFragment.java)

public class CrimeListFragment extends ListFragment {
private ArrayList mCrimes;
private boolean mSubtitleVisible;

private Callbacks mCallbacks;

public interface Callbacks {
    void onCrimeSelected(Crime crime);
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    mCallbacks = (Callbacks)activity;
}

@Override
public void onDetach() {
    super.onDetach();
    mCallbacks = null;
}
...

}
这样,CrimeListFragment有了调用托管activity的方法。另外,他不关心托管activity是谁。只要托管activity实现了CrimeListFragment.Callbacks接口,而CrimeListFragment中的代码不需要改变。

CrimeListFragment将托管的activity强转为CrimeListFragment.Callbacks对象。则意味着,托管activity必须实现CrimeListFragment.Callbacks接口。

实现回调接口(CrimeListActivity.java)

public class CrimeListActivity extends SingleFragmentActivity
implements CrimeListFragment.Callbacks {

@Override
protected Fragment createFragment() {
    return new CrimeListFragment();
}

@Override
protected int getLayoutResId() {
    return R.layout.activity_masterdetail;
}

public void onCrimeSelected(Crime crime) {
}
...

}
最终,在onListItemClick(…)方法里以及在用户创建新crime时,CrimeListFragment将调用onCrimeSelected(Crime)方法。 当onCrimeSelected(Crime)方法被调用时,CrimeListActivity需要完成以下二选一的任务:

设备是手机:启动新的CrimePagerActivity。
设备是平板:将CrimeFragment放入detailFragmentContainer中。
根据条件启动CrimeFragment(CrimeListActivity.java)

public void onCrimeSelected(Crime crime) {
if (findViewById(R.id.detailFragmentContainer) == null) {
// 如果布局中没有包含detailFragmentContainer,
// 说明设备是手机。于是应该启动新的CrimePagerActivity
Intent i = new Intent(this, CrimePagerActivity.class);
i.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
startActivityForResult(i, 0);
} else {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment oldDetail = fm.findFragmentById(R.id.detailFragmentContainer);
Fragment newDetail = CrimeFragment.newInstance(crime.getId());
// 创建一个fragment事务,将我们需要的CrimeFragment
// 添加到detailFragmentContainer中。如果之前就有CrimeFragment存在,
// 首先应从detailFragmentContainer中移除它
if (oldDetail != null) {
ft.remove(oldDetail);
}
ft.add(R.id.detailFragmentContainer, newDetail);
ft.commit();
}
}
最后应该在CrimeListFragment类中,启动新的CrimePagerActivity的地方,调用onCrimeSelected(Crime)方法。 在CrimeListFragment.java中修改onListItemClick(…)和onOptionsItemSelected(MenuItem)方法实现对Callbacks.onCrimeSelected(Crime)方法的调用。

调用全部回调方法(CrimeListFragment.java)

public void onListItemClick(ListView l, View v, int position, long id) {
// get the Crime from the adapter
Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
mCallbacks.onCrimeSelected(c);
}

public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_crime:
Crime crime = new Crime();
CrimeLab.get(getActivity()).addCrime(crime);
((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
mCallbacks.onCrimeSelected(crime);
return true;

}
}
总结

上面CriminalIntent的例子和第二张图片类比:

enter image description here

enter image description here

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值