2011-09-22 6 views
7

내 안드로이드 프로젝트에 MVP 패턴을 사용할 계획입니다. 몇 가지 샘플 코드를 작성 했으므로 제대로 구현했는지 알고 싶습니다. 코드에 대한 의견을 말하고 제안 사항을 게시하십시오.안드로이드 MVP 패턴에 대한 의견

내 활동 클래스 내 BaseView 클래스에서 확장하고 인터페이스를 구현하고 있습니다. 이 액티비티는 단순히 새 스레드에서 웹 서비스를 호출하고 textview의 값을 업데이트합니다.

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"); 
     } 
    } 


} 

내 액티비티 클래스 : 내 액티비티 클래스에는 텍스트 뷰와 버튼이 있습니다. 버튼을 누르면 웹 서비스를 호출하여 발표자 클래스의 데이터를 가져옵니다. 발표자 클래스는 웹 서비스를 호출하여 응답을 구문 분석하고 액티비티의 텍스트 뷰에 값을 설정합니다.

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")); 
     } 

    } 

아래 인터페이스는 활동 클래스에서 구현되고, 활동 클래스의 인스턴스는 표현 자 클래스의 생성자 인터페이스 객체로 전송된다. 후반 : 죄송

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

그럼 뭐가 궁금한가요? – Pedantic

+2

MVP 패턴을 올바르게 구현했는지 알고 싶습니다. –

+1

호기심에서 벗어 났지만'BaseView'는'Activity'를 연장합니까? (너무 명확한 경우 미안) – Quv

답변

12

나는 안드로이드에서 사용 MVP 이런 식으로했습니다.

활동은 발표자입니다. 모든 발표자는 모델에 대한 링크를 가지고 있습니다 (때로는 서비스, 때로는 작업에 따라 다름) 및보기 (들). 나는 커스텀 뷰를 생성하고 그것을 액티비티를위한 컨텐트 뷰로 설정한다.

은 참조 :

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); 
    } 
} 

또한, 나는이 주제 here을 논의했습니다.

활동을보기로 간주해서는 안된다는 경고를 보내야합니다. Activity를 뷰 구성 요소로 고려한 PureMVC를 사용하여 썼을 때 우리는 매우 만족스럽지 않았습니다. 액티비티는 컨트롤러/발표자/뷰 모델에 매우 적합합니다 (모든 것을 시도해 봤는데 MVP가 가장 맘에 든다).보기 자체가 아니지만 뷰 (보기, 대화 상자 등) 관리에 뛰어난 도구가 있습니다.

+5

커스텀 발표자가있는 활동을보기로 추천하는 많은 기사를 보았습니다. 그러나 솔직히 말해서 내 접근 방식은 실제로 훨씬 더 의미가 있습니다 (유지 관리가 더 쉬운 것처럼 보입니다) . 나는 꽤 경험이 부족한 Java 개발자이다. 그래서 나는 무엇을 알고 있는가? –

+0

더 많은 예제를 공유 할 수 있습니까? 위의 샘플은 조금 간단하고, 다소 안드로이드 MVP 주위에 내 머리를 얻으려고 노력하고 있습니다. – Jimmy

+0

나는 오픈 소스 프로젝트가 없습니다. 사실, 저는 Activity가 컨트롤러에 비해 너무 큰 작업을 종종 해결합니다. 경량 제어기에 적합한 조각이며, 활동은 수퍼 제어기입니다. 또한, 팀 리더로서의 내 경험으로 MVP/MVC/MVVM이 어렵다는 것을 알 수 있습니다. 동료들에게 어려운 점은 "행동 패턴이 적합합니다"입니다. 원한다면 niko89a-AT-yandex.ru로 메일을 보내주십시오. – QuickNick

관련 문제