AndroidAndroid开发程序员

Android之MVP模式

2016-04-06  本文已影响373人  许晓北

前几天和朋友闲扯聊到了MVP模式,在项目开发中你选择了MVP模式你就最好坚持做下去,因为后期你发现坑越来越大想换回MVC模式就准备推到重来。当然MVP既然能出现那么必然有它的优点。
MVP所对应的意义:M-Model-模型、V-View-视图、P-Presenter-表示器。
先看下整体项目包:


MVP包结构

首先建立一个接口ViewImp:

public interface ViewImp{
//初始化view
public  void init(LayoutInflater inflater,ViewGroup container);
//返回view对象
public android.view.View getView();
}

接着我们建立父类BasePresenterActivity<V extends ViewImp>:

public abstract class BasePresenterActivity<V extends ViewImp> extends Activity {   
protected V vu;   
protected FragmentManager fm;  
public EventBus bus;   
   @Override    
protected void onCreate(Bundle savedInstanceState) {             
  super.onCreate(savedInstanceState);       
   try {           
     //获取到fragmentmanager   
     fm = getFragmentManager();       
 //获取到EventBus 主要作用用来解耦     
   bus = EventBus.getDefault();    
 //获取子类
   vu = (V) getVuClass().newInstance();    
    //初始化view       
   vu.init(getLayoutInflater(), null);  
      setContentView(vu.getView());  
      //绑定数据       
   onBindVu();     
   } catch (Exception e) {     
   e.printStackTrace();    
  }   
 }  
  //绑定数据 
protected void onBindVu() {   

} 

//返回当前的View的对象  
 protected abstract Class<MainView> getVuClass();

//可编辑    
   @Override  
protected final void onResume() {   
 afterOnResume();     
 super.onResume();  
  }    
 public void afterOnResume() {    }  
 // 不可编辑    
  @Override   
protected final void onPause() {    
 beforeOnPause();      
 super.onPause();   
}  
public void beforeOnPause() {    }   
}  

我们接着建立子类MAinActivity:

public class MainActivity extends BasePresenterActivity<MainView> {    
  // 绑定数据    
  @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
  @Override 
  protected void onBindVu() {   
 super.onBindVu();   
 //第一个参数表示替换内容的ID 
fm.beginTransaction().replace(vu.getContentId(),ListFragment.newInstance()).commit();  
  }
 @Override   
protected Class<MainView> getVuClass() {     
 return MainView.class; 
    }
// 处理业务逻辑     
@Override 
 public void beforeOnPause() {   
 super.beforeOnPause();     
 bus.unregister(this);  
  }   
// 处理业务逻辑   
 @Override  
public void afterOnResume() {    
super.afterOnResume();    
bus.registerSticky(this);  
   }    
}

在MainActivity里面看到我们需要传递一个视图MainView:

public class MainView implements ViewImp {  
public android.view.View view;
public TextView tv;  
private FrameLayout content;   
//初始化View    
@Override    
public void init(LayoutInflater inflater, ViewGroup container) {      
//布局就是一个FrameLayout
view= inflater.inflate(R.layout.activity_main,container,false);     
content=(FrameLayout) view.findViewById(R.id.content);  
    } 
public int getContentId(){  
    return  content.getId();
    }   
 //返回view  
@Override    
public android.view.View getView() {  
  return view;  
       }
 }

从MainActivity里面看到实际我们用ListFragment替换了MainView视图里面的FrameLayout,既然要建立fragment肯定要先建立父类BasePresenterFragment<V extends ViewImp>:

 public abstract class BasePresenterFragment<V extends ViewImp> extends Fragment     {   
    public V vu;    
 // fragment初始化时候调用的方法    
  @Override   
  public void onCreate(Bundle savedInstanceState) {  
  }   
  //  创建一个view  
 @Override    
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container,   Bundle savedInstanceState) {     
  android.view.View view = null;  
    try {       
  //同BasePresenterActivity其实同样获取子类,在子类的视图中初始化
   vu = (V) getVuClass().newInstance();      
    vu.init(inflater, container); 
         onBindVu();      
     view = vu.getView();   
    } catch (Exception e) {    
      e.printStackTrace();     
  }        
   return view;
 }   
 @Override  
  public void onDestroyView() { 
   onDestroyVu();     
    vu=null;   
   super.onDestroyView(); 
   }   
 private void onDestroyVu() {    } 
  //绑定view    
  public void onBindVu() {    }    
// 获取view对象   
public abstract Class<V> getVuClass();
 }

接着看子类ListFragment:

  public class ListFragment extends BasePresenterFragment<ListView>{   
  ListViewAdapter adapter= new ListViewAdapter();
  ViewCallback<Integer> selectCallback= new ViewCallback<Integer>() {   
   @Override     
   public void execute(Integer result) {    
    }  
  };  
    @Override   
  public void onBindVu() {     
    super.onBindVu();    
    vu.setListAdapter(adapter); 
     vu.selectCallback(selectCallback); 
  }    
 @Override   
public Class<ListView> getVuClass() {    
   return ListView.class;  
}  
// 实例化当前对象      
 public static ListFragment newInstance(){    
  return  new ListFragment();   
  }
 }

通过ListFragment发现视图在ListView中,而在fragment中我们进行的是逻辑处理。
ListView:

public class ListView implements ViewImp {    
private android.widget.ListView listview;    
private android.view.View view;   
public ViewCallback<Integer> selectCallback;  
  @Override 
  public void init(LayoutInflater inflater, ViewGroup container) {    
   view = inflater.inflate(R.layout.list, container, false); 
   listview=(android.widget.ListView)  view.findViewById(R.id.listview);        
    listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {     
     @Override     
     public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {           
   if(selectCallback!=null){      
          selectCallback.execute(position);      
       }       
    }    
   }); 
 }  
 @Override   
public android.view.View getView() {        
    return null; 
   }  
 public void setListAdapter(ListViewAdapter adapter) {   
   listview.setAdapter(adapter);   
  }   
public void selectCallback(ViewCallback<Integer> selectCallback) { 
   }
}

在这个地方我们建立了一个接口 ViewCallback<T>,这样我们就可以将listview的点击事件逻辑放在fragment中进行,将view与逻辑分开。

 public interface ViewCallback<T> {  
      public void execute(T result);
 }

于此同时我们建立了适配器ListAdapter,为了方便处理,我们同样建立了BasePresenterAdapter<V extends ViewImp>:

public  abstract  class BasePresenterAdapter<V extends ViewImp> extends BaseAdapter {    
public V vu;
private V vuClass;
@Override
public android.view.View getView(int position, android.view.View convertView, ViewGroup parent) {
    if(convertView==null){  
      //获取填充布局
        LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       try { 
           vu= (V) getVuClass().newInstance();
            //初始化view 
           vu.init(inflater,parent);
            //获取当前view
            convertView= vu.getView(); 
           convertView.setTag(vu);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }else{ 
      vu= (V) convertView.getTag();
    }
    if(convertView!=null){ 
       //绑定数据 
       onBindListItemVu(position);
    }
    return convertView;
  }
public abstract void onBindListItemVu(int position);
public abstract Class<V> getVuClass();
}

因为所有的getview可以抽取出来放在父类,子类ListViewAdapter:

public class ListViewAdapter extends BasePresenterAdapter <ListItemView>{
List<String> titles= new ArrayList<String>(Content.VALUE_MAP.keySet());
@Override
public void onBindListItemVu(int position) {
    String title = titles.get(position);
    vu.setTitle(title);
}
@Override
public Class<ListItemView> getVuClass() {
    return ListItemView.class;
}
@Override
public int getCount() {
    return titles.size();
}
@Override
public Object getItem(int position) {
    return titles.get(position);
}
public String getTitle(int postion) {
  return (String) getItem(postion);
}
@Override
public long getItemId(int position) {
    return position;
 }
}

实际在这个Listview中item的布局我简单放了有一个textview,ListItemView:

public class ListItemView implements ViewImp {
public TextView textview;
public android.view.View view;
@Override
public void init(LayoutInflater inflater, ViewGroup container) {
     view = inflater.inflate(R.layout.ipsum_list_item, container, false);
     textview = (TextView) view.findViewById(R.id.text);
}
@Override
public android.view.View getView() { 
   return view;
}
public void setTitle(String title) {
    textview.setText(title);
  }
}

里面数据我偷懒就放在bean里面 请别打我。。。

public class Content {
public String title;
public String body;
public Content(String title, String body) {
    this.title = title;
    this.body = body;
}
//所有数据
public static Map<String,Content> VALUE_MAP=new HashMap<String,Content>();
static {
    VALUE_MAP.put("敲敲demo",new Content("真的敲敲demo","自己敲demo"));
  }
 }

刚开始用的时候可能比较麻烦,当你父类完成以后后期的复用还是挺给力的。
源码地址 https://github.com/Xu-xiaobei/MVP_demo

上一篇下一篇

猜你喜欢

热点阅读