衆所周知,在android裏面充斥着衆多的監聽器,如一個按鈕具備的OnClickListener,能對按鈕的點擊事件進行監聽,這些監聽器一般是一個接口,咱們能夠經過實現接口裏的回調方法,執行事件處理。而AsyncTask也能經過其回調方法在恰當的時間執行異步任務(doInBackground()中),而且在執行完畢後回調到onPostExecute(),咱們能夠在onPostExecute下面得到異步任務的結果,並使結果安全地在UI線程中顯示。AsyncTask是個抽象類,這些回調方法多是抽象方法,也多是普通的方法,像doInBackground是抽象方法,強制使用AsyncTask的人去實現,而onPostExecute等回調方法則不是抽象的,使用者可選地對其進行重寫。android
回調方法這種設計在我看來是如此的精妙絕倫,它總能在恰到好處的時間返回和執行正確的事。上面提到了兩種實現回調方法的方式:1.是抽象的抽象,面向接口,全部監聽器中的方法都必須實現。2.是單純的抽象,可以可選地進行回調須要的方法。下面我就本身寫了兩種方式的回調,及說明使用場景。安全
方式一:使用接口(使用場景:自定義View時做爲事件監聽器)app
/** * 自定義列表頭視圖 * * @author Change * */ public class ListHeadView extends LinearLayout implements OnClickListener { private OnHeadControlListener colLis; private CheckBox c_all; private TextView field1, field2, field3, field4; private Button controlBtn; private final int count = 4; public ListHeadView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); inflateView(context); } public ListHeadView(Context context, AttributeSet attrs) { super(context, attrs); inflateView(context); } public ListHeadView(Context context) { super(context); inflateView(context); } private void initView() { c_all = (CheckBox) this.findViewById(R.id.c_all); field1 = (TextView) findViewById(R.id.field1); field2 = (TextView) findViewById(R.id.field2); field3 = (TextView) findViewById(R.id.field3); field4 = (TextView) findViewById(R.id.field4); controlBtn = (Button) findViewById(R.id.controlBtn); controlBtn.setOnClickListener(this); c_all.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { colLis.onCheckAllChange(isChecked);// 調用1 } }); } private void inflateView(Context context) { View.inflate(context, R.layout.list_head, this); initView(); } public void setTexts(String[] texts) { if(texts.length>=count){ field1.setText(texts[0]); field2.setText(texts[1]); field3.setText(texts[2]); field4.setText(texts[3]); }else{ throw new ArrayIndexOutOfBoundsException("you don't have tomany fields!"); } } public void setButtonResource(int resid){ controlBtn.setBackgroundResource(resid); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.controlBtn: colLis.onClickRightBtn();// 調用2 break; default: break; } } /** * 回調接口,提供按鈕和複選框的監聽 * * @author Change * */ public interface OnHeadControlListener { /** * 點擊右邊按鈕後觸發 */ public void onClickRightBtn(); /** * 複選框狀態改變後觸發 * * @param isChecked */ public void onCheckAllChange(boolean isChecked); } /** * 設置監聽器 * * @param colLis */ public void setOnHeadControlListener(OnHeadControlListener colLis) { this.colLis = colLis; } }
那麼,咱們在使用的時候就能夠經過異步
setOnHeadControlListener方法去設置監聽器了。
ListHeadView headView = new ListHeadView(context); headView.setOnHeadControlListener(new OnHeadControlListener() { @Override public void onClickRightBtn() { Toast.makeText(context, "點擊按鈕", Toast.LENGTH_SHORT).show(); } @Override public void onCheckAllChange(boolean isChecked) { Toast.makeText(context, "選擇變化爲"+isChecked, Toast.LENGTH_SHORT).show(); } });
方式二:使用抽象類(異步任務結果返回)ide
/** * apk搜索器 * * @author Change * */ public abstract class ApkFileSearcher { private String keyword;// 搜索關鍵字 private static final String TAG = ApkFileSearcher.class.getSimpleName(); public ApkFileSearcher(String keyword) { this.keyword = keyword; } /** * 從列表中得到關鍵字匹配的新列表 * * @param allApps * @return */ public List<AppsBean> onSearchIn(List<AppsBean> allApps) { List<AppsBean> results = new ArrayList<AppsBean>(); for (AppsBean app : allApps) { if (app.appName.contains(keyword) || app.pkgName.contains(keyword)) { results.add(app); } } allApps.clear(); allApps.addAll(results); return allApps; } /** * 抽象方法:回調搜索結果 * * @param result */ public abstract void onSearchFinished(List<AppsBean> result); /** * 本地異步搜索 * * @param allApps */ public void startAsyncLocalSearch(final List<AppsBean> allApps) { new AsyncTask<Void, Void, List<AppsBean>>() { @Override protected List<AppsBean> doInBackground(Void... params) { return onSearchIn(allApps); } @Override protected void onPostExecute(List<AppsBean> result) { onSearchFinished(result);// 調用,傳入結果 }; }.execute(); }
使用的時候便要實現其中的抽象方法。this
final ApkFileSearcher searcher = new ApkFileSearcher(keyword) { @Override public void onSearchFinished(List<AppsBean> result) { //在界面對結果進行處理。如傳入並構建列表適配器 } };
再次感慨這前人偉大的發明,無敵的回調設計,固然,使用回調方法也有弊端,我的認爲大量使用匿名內部類將下降代碼的可讀性,用的時候須要慎重,不過,貴在用之方便,依舊強調它的特色--恰到好處。spa