2011-09-22 12 views
7

Estoy planeando usar el patrón de MVP para mi nuevo proyecto de Android. He hecho un código de muestra y me gustaría saber si lo he implementado correctamente. Por favor, den comentarios sobre el código y también publiquen sus sugerencias.Comentarios sobre mi patrón de MVP para Android

mi clase de actividad Lo estoy extendiendo desde mi clase BaseView y estoy implementando una interfaz. esta actividad simplemente llama a un servicio web en un nuevo hilo y actualiza el valor en la vista de texto.

public class CougarTestView extends BaseView implements ICougarView, 
     OnClickListener { 
    CougarTestPresenter _presenter; 
    public String activityName = "CougarHome"; 

    /** Called when the activity is first created. */`enter code here` 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState, activityName); 
     setContentView(R.layout.main); 
     _presenter = new CougarTestPresenter(this); 
     getSubmitBtn().setOnClickListener(this); 
     getCallInfoBtn().setOnClickListener(this); 

    } 

    private Button getCallInfoBtn() { 
     return (Button) findViewById(R.id.btn_callinfo); 
    } 

    public void setServiceValue(String retVal) { 
     // TODO Auto-generated method stub 
     getResultLabel().setText(retVal); 
     setPbar(false); 
     // toastMsg(retVal); 
    } 

    public void ResetPbar() { 
     getProgressBtn().setProgress(0); 
    } 

    public void setProcessProgress(int progress) { 

     if (getProgressBtn().getProgress() < 100) { 
      getProgressBtn().incrementProgressBy(progress); 
     } else { 
      setPbar(false); 
     } 
    } 

    private TextView getResultLabel() { 
     return (TextView) findViewById(R.id.result); 
    } 

    private Button getSubmitBtn() { 
     return (Button) findViewById(R.id.btn_triptype); 
    } 

    private ProgressBar getProgressBtn() { 
     return (ProgressBar) findViewById(R.id.pgs_br); 
    } 

    public void setPbar(boolean visible) { 
     if (!visible) { 
      getProgressBtn().setVisibility(View.GONE); 
     } else 
      getProgressBtn().setVisibility(View.VISIBLE); 
    } 

    @Override 
    public void setHttpResult(String retVal) { 
     // TODO Auto-generated method stub 
     setServiceValue(retVal); 
    } 

    private void toastMsg(String msg) { 
     Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); 
    } 

    public void onClick(View v) { 
     // TODO Auto-generated method stub 
     switch (v.getId()) { 
     case R.id.btn_triptype: {   
      try { 
       _presenter.valueFromService(RequestType.CallInfo, 0); 
      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      break; 
     } 

     default: 
      setServiceValue("default"); 
     } 
    } 


} 

Mi clase de actividad: en mi clase de actividad estoy teniendo una vista de texto y un botón. cuando presiono el botón, llama al servicio web para obtener los datos en la clase del presentador. la clase de presentador llama al servicio web analiza la respuesta y establece el valor en la vista de texto de la actividad.

My presenter class 


public class CougarTestPresenter { 
    ICougarView mIci; 
    RequestType mRtype; 
    public String result= "thisi s result i"; 
    Handler mHandle; 


    public CougarTestPresenter(ICougarView ici) { 
     mIci = ici; 

    } 
    public void valueFromService(RequestType type, int x) throws Exception{ 
     String url = getURLByType(type); 

     // GetServiceresult service = new GetServiceresult(); 
     // service.execute(url); 
     Handler handle = new Handler() { 
      public void handleMessage(Message msg) { 
       switch (msg.what) { 

       case Globals.IO_EXPECTION: { 
        Toast.makeText(mIci.getContext(), msg.toString(), 
          Toast.LENGTH_LONG).show(); 
        NetworkConnectivityListener connectivityListener = NetworkConnectivityListener 
          .getInstace(); 
        mHandle = CustomHandler.getInstance(mIci.getContext(), 
          connectivityListener, mIci); 
        connectivityListener.registerHandler(mHandle, 
          Globals.CONNECTIVITY_MSG); 
        connectivityListener.startListening(mIci.getContext()); 
        mIci.setPbar(false); 
       } 
        break; 
       case Globals.RHAPSODY_EXCEPTION:{ 
        ExceptionInfo exInfo =null; 
         try { 
          exInfo = Utility.ParseExceptionData(msg.obj.toString()); 

         } catch (JSONException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } catch (Exception e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         }      
         mIci.setServiceValue(exInfo.Message + exInfo.Type +exInfo.Detail); 

       //  new HandleRhapsodyException(mIsa, exInfo); 
       } 
       break; 
       default: { 
        Toast.makeText(mIci.getContext(), msg.toString(), 
          Toast.LENGTH_LONG).show(); 
        mIci.setServiceValue(msg.obj.toString()); 
       } 
       } 

      } 
     }; 

     ServiceResult thread = new ServiceResult(handle, url); 
     mIci.setPbar(true); 
     thread.start(); 

    } 

    public String getURLByType(RequestType type) { 
     // TODO Auto-generated method stub 
     switch (type) { 
     case CallInfo: { 
      return ("www.gmail.com"); 
     } 
     case TripType: { 
      return ("www.google.com"); 
     } 
     default: 
      return ("www.cnet.com"); 

     } 
    } 

    private class ServiceResult extends Thread { 
     Handler handle; 
     String url; 

     public ServiceResult(Handler handle, String url) { 
      this.handle = handle; 
      this.url = url; 
     } 

     public void run() { 
      sendExceptionLog(handle); 

     } 
    } 

    public void sendExceptionLog(Handler handle) { 

     DebugHttpClient httpClient = new DebugHttpClient(); 

     HttpGet get = new HttpGet(
       "https://192.168.194.141/TripService/service1/"); 
     try { 
      HttpResponse response = httpClient.execute(get); 

      HttpEntity r_entity = response.getEntity(); 
      String xmlString = EntityUtils.toString(r_entity); 
      // setdvrid.setText(xmlString + " " 
      // + response.getStatusLine().getStatusCode()); 

      httpClient.getConnectionManager().shutdown(); 

      if (response.getStatusLine().getStatusCode() != 200) { 
       handle.sendMessage(Message.obtain(handle, Globals.RHAPSODY_EXCEPTION, 
         xmlString)); 
      result= Utility.ParseExceptionData(xmlString).Message; 
      } 
      else 
      { 
       handle.sendMessage(Message.obtain(handle, Globals.SERVICE_REPONSE, 
         response.getStatusLine().getStatusCode() 
           + response.getStatusLine().getReasonPhrase() 
           + xmlString)); 
      } 

     } catch (ClientProtocolException e) { 
      // TODO Auto-generated catch block 
      handle.sendMessage(Message.obtain(handle, Globals.OTHER_EXPECTION, 
        e.getMessage().toString() + "she")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      handle.sendMessage(Message.obtain(handle, Globals.IO_EXPECTION, e 
        .getMessage().toString() + "he")); 
     } catch (Exception e) { 
      handle.sendMessage(Message.obtain(handle, Globals.OTHER_EXPECTION, 
        e.getMessage().toString() + "it")); 
     } 

    } 

la interfaz a continuación se implementa en la clase de actividad y la instancia de la clase de actividad se envía como objeto de interfaz al constructor de la clase presentador.

my view interface 

public interface ICougarView { 
public void setServiceValue(String retVal); 
public void setProcessProgress(int progress); 
public void setPbar(boolean b); 
public void ResetPbar(); 
public Context getContext(); 
} 
+0

¿Cuál es su pregunta? – Pedantic

+2

Me gustaría saber si he implementado el patrón de MVP correctamente. –

+1

Solo por curiosidad, pero ¿su 'BaseView' extiende' Activity'? (Lo siento si es demasiado obvio) – Quv

Respuesta

12

Lo siento por la tarde :) He uso MVP en Android esta manera.

Las actividades son presentadores. Cada presentador tiene un enlace a un modelo (s) (a veces se trata de servicios, a veces no, dependiendo de la tarea) y para ver (s). Creo una vista personalizada y la configuro como la vista de contenido para la actividad.

Ver:

public class ExampleModel { 
    private ExampleActivity presenter; 

    public ExampleModel(ExampleActivity presenter) { 
     this.presenter = presenter; 
    } 
    //domain logic and so on 
} 

public class ExampleActivity extends Activity { 
    private ExampleModel model; 
    private ExampleView view; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     model = new ExampleModel(this); 
     view = new ExampleView(this); 
     setContentView(view); 
    } 
    // different presenter methods 
} 

public class ExampleView extends LinearLayout { 

    public ExampleView(Context context) { 
     super(context); 
    } 
} 

Además, he discutido este tema here.

Debo advertirle que la actividad no se debe considerar como la vista. Tuvimos muy mala experiencia con esto, cuando escribimos con PureMVC que consideraba la actividad como componente de visualización. La actividad es excelente para el modelo de controlador/presentador/vista (he probado todos, me gusta más MVP), tiene una excelente instrumentación para administrar las vistas (Vista, Diálogo, etc.) mientras que no es una vista en sí misma.

+5

He visto una gran cantidad de artículos que recomiendan Activity como la vista, con un Presenter personalizado, pero para ser sincero, su enfoque realmente tiene mucho más sentido para mí (y parece más fácil de mantener) . Aunque soy un desarrollador Java bastante inexperto, ¿qué sé yo? –

+0

¿Tiene algún ejemplo más completo que pueda compartir? La muestra anterior es un poco breve, un poco tratando de entender MVP de Android también :) – Jimmy

+0

No tengo proyectos de código abierto. De hecho, a menudo resuelvo tales tareas donde la Actividad es demasiado grande para el controlador. Es un Fragmento que es adecuado para un controlador liviano, y la Actividad es un supercontrolador. Además, mi experiencia como líder de equipo puede decirme que no es MVP/MVC/MVVM lo que es difícil. Lo difícil para mis colegas es "qué patrón de comportamiento es adecuado". Si lo desea, puede enviarme un correo electrónico a niko89a-AT-yandex.ru. – QuickNick