各司其职:在Android适配器中使用委托者模式
【这是一个线索】适配器君从不甘当线索,同样是设计模式,适配器模式不是今天的主题,今天的主题是在适配器中如何使用委托者模式以明确设计中的各元素的分工。
一个具有适配器View的界面,Activity作为MVC模式中的控制器,数据控制应当由它完成。那么,为了让Adapter只负责数据界面绑定,Activity负责控制数据的变动,委托者模式这个时候就应该勇敢地站出来,让Adapter中可能涉及到的控制委托给Activity去处理。
我又要举例子了,代码君憋不住了,它在下面↓↓↓↓↓↓
1 package com.change.delegateforadapterdemo; 2 3 import java.util.List; 4 5 import android.content.Context; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.view.ViewGroup; 10 import android.widget.BaseAdapter; 11 import android.widget.Button; 12 import android.widget.TextView; 13 14 /** 15 * 委托者模式运用在adapter中 16 * @author Change 17 * 18 */ 19 public class DelegateForAdapter extends BaseAdapter { 20 private List<String> names; 21 private LayoutInflater mInflater; 22 private DataControlDelegate mDelegate; 23 public DelegateForAdapter(Context ctx,List<String> _names) { 24 this.names = _names; 25 mInflater = LayoutInflater.from(ctx); 26 } 27 /** 28 * 委托接口,用于对adapter中的数据进行操作,此处只提供了一个删除单条数据的方法。 29 * @author Change 30 * 31 */ 32 public static interface DataControlDelegate{ 33 /** 34 * 删除数据 35 * @param name 36 */ 37 public void removeItem(String name); 38 } 39 40 @Override 41 public int getCount() { 42 return names.size(); 43 } 44 45 @Override 46 public Object getItem(int arg0) { 47 return names.get(arg0); 48 } 49 50 @Override 51 public long getItemId(int arg0) { 52 return arg0; 53 } 54 55 @Override 56 public View getView(int arg0, View arg1, ViewGroup arg2) { 57 ViewHolder holder = null; 58 if(null==arg1){ 59 arg1 = mInflater.inflate(R.layout.item_name, null); 60 holder = new ViewHolder(); 61 holder.name = (TextView)arg1.findViewById(R.id.name); 62 holder.remove = (Button)arg1.findViewById(R.id.remove); 63 arg1.setTag(holder); 64 }else{ 65 holder = (ViewHolder)arg1.getTag(); 66 } 67 final String name = names.get(arg0); 68 holder.remove.setOnClickListener(new OnClickListener() { 69 @Override 70 public void onClick(View arg0) { 71 if(null!=mDelegate) 72 mDelegate.removeItem(name);//删除行为 73 } 74 }); 75 holder.name.setText(name); 76 return arg1; 77 } 78 static class ViewHolder{ 79 public TextView name; 80 public Button remove; 81 } 82 /** 83 * 设置委托者 84 * @param _delegate 85 */ 86 public void setDataControlDelegate(DataControlDelegate _delegate){ 87 this.mDelegate = _delegate; 88 } 89 90 }
【委托者接口】大部分设计模式都由接口做主导,所以,不得不提它,上面代码标红的就是我们的委托者接口,实现它的模块都会沦为被委托对象。上面紫色部分便是需要委托的内容,本来点击删除的行为是在列表项里完成的,但为了分工明确,我们把它委托出去了,那是时候看看那可怜的被委托对象了。
【被委托对象】悲惨的Activity又要帮adapter完成工作了,它实现了委托者接口,删除数据项的行为对它来说,轻而易举。我们在生命周期onResume()中绑定委托对象,并且在onPause()时去除,就能保证activity在屏幕显示的时候才作为委托者。
1 package com.change.delegateforadapterdemo; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.os.Bundle; 8 import android.view.Menu; 9 import android.widget.ListView; 10 import android.widget.Toast; 11 12 import com.change.delegateforadapterdemo.DelegateForAdapter.DataControlDelegate; 13 14 /** 15 * 实现adapter中的数据委托接口,把所有的行为让activity来控制吧。 16 * @author Change 17 * 18 */ 19 public class MainActivity extends Activity implements DataControlDelegate{ 20 private List<String> names = new ArrayList<String>(); 21 private DelegateForAdapter adapter; 22 @Override 23 protected void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_main); 26 initDatas(); 27 ListView lv = (ListView)findViewById(R.id.lv); 28 adapter = new DelegateForAdapter(this, names); 29 lv.setAdapter(adapter); 30 } 31 32 @Override 33 protected void onResume() { 34 super.onResume(); 35 adapter.setDataControlDelegate(this);//绑定委托对象 36 } 37 38 @Override 39 protected void onPause() { 40 super.onPause(); 41 adapter.setDataControlDelegate(null);//去除绑定委托对象 42 } 43 44 @Override 45 public boolean onCreateOptionsMenu(Menu menu) { 46 // Inflate the menu; this adds items to the action bar if it is present. 47 getMenuInflater().inflate(R.menu.main, menu); 48 return true; 49 } 50 51 private void initDatas(){ 52 for(int i=0;i<10;i++){ 53 names.add("name"+i); 54 } 55 } 56 57 @Override 58 public void removeItem(String name) { 59 names.remove(name); 60 adapter.notifyDataSetChanged(); 61 Toast.makeText(this, "已删除"+name, Toast.LENGTH_SHORT).show(); 62 } 63 64 }
【依然如此简单】removeItem(),一个方法代表一个行为,轻松实现删除的需求,notifyDataSetChanged()通知后界面便发生了变化。到现在为止,一切都像我们想象的一样发生了。
【完整代码】github地址:https://github.com/ChangeWu/SomePoject/tree/master/DelegateForAdapterDemo