今天我要把前幾天所學的功能實作成一個簡單的接收API專案,這邊以FakeAPI的資料來接取。
大致上的功能是判斷輸入的帳號是否正確接著拿取到資料,並且是以MVP架構下去撰寫。
   <androidx.constraintlayout.widget.Guideline
       android:id="@+id/GLPersent01"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:orientation="horizontal"
       app:layout_constraintGuide_percent="0.1"/>
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/GLPersentvertcal01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.1"/>
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/GLPersentvertcal09"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.9"/>
    <TextView
        android:id="@+id/Account"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="帳號:"
        android:textAlignment="center"
        android:textSize="25dp"
        app:layout_constraintTop_toTopOf="@+id/GLPersent01"
        app:layout_constraintStart_toStartOf="@id/GLPersentvertcal01"/>
    <EditText
        android:id="@+id/ETaccount"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="請輸入帳號"
        app:layout_constraintTop_toTopOf="@id/GLPersent01"
        app:layout_constraintStart_toEndOf="@id/Account"
        app:layout_constraintEnd_toEndOf="@id/GLPersentvertcal09"/>
    <TextView
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="密碼:"
        android:textAlignment="center"
        android:textSize="25dp"
        app:layout_constraintTop_toBottomOf="@id/Account"
        app:layout_constraintStart_toStartOf="@id/GLPersentvertcal01"/>
    <EditText
        android:id="@+id/ETpassword"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="請輸入密碼"
        app:layout_constraintTop_toBottomOf="@id/Account"
        app:layout_constraintStart_toEndOf="@id/password"
        app:layout_constraintEnd_toEndOf="@id/GLPersentvertcal09"/>
    <Button
        android:id="@+id/EnterButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="確定"
        app:layout_constraintTop_toBottomOf="@id/password"
        app:layout_constraintStart_toStartOf="@id/GLPersentvertcal01"
        app:layout_constraintEnd_toEndOf="@id/GLPersentvertcal09"
        android:layout_marginTop="10dp"
        tools:ignore="MissingConstraints" />
    <TextView
        android:id="@+id/showStatus"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:hint="結果顯示區"
        android:textAlignment="center"
        android:textSize="18dp"
        android:background="@color/teal_200"
        app:layout_constraintTop_toBottomOf="@id/EnterButton"
        app:layout_constraintStart_toStartOf="@id/GLPersentvertcal01"
        app:layout_constraintEnd_toEndOf="@id/GLPersentvertcal09"
        app:layout_constraintBottom_toBottomOf="parent"/>
    //Retrofit2
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    // 以Singleton模式建立
    private static SiteManager mInstance = new SiteManager ();
    private APIService myAPIService;
    private SiteManager () {
        // 設置baseUrl即要連的網站,addConverterFactory用Gson作為資料處理Converter
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://jsonplaceholder.typicode.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        myAPIService = retrofit.create(APIService.class);
    }
    public static SiteManager getInstance() {
        return mInstance;
    }
    public APIService getAPI() {
        return myAPIService;
    }
    @GET("posts")
    Call<List<APIResponse>> response();
    private int userId;
    private int id;
    private String title;
    private String body;
    @Override
    public String toString() {
        return "APIResponse{" +
                "userId=" + userId +
                ", id=" + id +
                ", title='" + title + '\'' +
                ", body='" + body + '\'' +
                '}';
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
}
    interface View{
        void setString(String string);
    }
    interface Presenter{
        void onButtonClick(String Password,String Account);
    }
    interface Model{
        interface FinishListener {
            void OnFinished(String string);
        }
        void OnNext(Contract.Model.FinishListener OnFinished);
    }
三個對應的Class
MainActivity(View)
public class MainActivity extends AppCompatActivity implements Contract.View{
    private TextView showText;
    private Button button;
    private EditText account,password;
    private Contract.Presenter presenter;
    private static String TAG = "View";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.EnterButton);
        showText = findViewById(R.id.showStatus);
        account = findViewById(R.id.ETaccount);
        password = findViewById(R.id.ETpassword);
        presenter = new Presenter(this,new Model());
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e(TAG, "onClick: ");
                presenter.onButtonClick(account.getText().toString(),password.getText().toString());
            }
        });
    }
    @Override
    public void setString(String string) {
        Log.e(TAG, "setString: ");
        showText.setText(string);
    }
}
public class Presenter implements Contract.Presenter,Contract.Model.FinishListener{
    private Contract.View mainView;
    private Contract.Model model;
    private static String TAG = "Presenter";
    private String password,account;
    public Presenter(Contract.View mainView, Contract.Model model) {
        this.mainView = mainView;
        this.model = model;
    }
    @Override
    public void OnFinished(String string) {
        if(mainView != null){
            Log.e(TAG, "OnFinished: ");
            mainView.setString(string);
        }
    }
    @Override
    public void onButtonClick(String Password,String Account) {
        Log.e(TAG, "onButtonClick: ");
        account = Account;
        password = Password;
        Log.e(TAG, "onButtonClick: "+password+"  "+account );
        if(account.equals("jay") && password.equals("jay")){
            Log.e(TAG, "Account is Correct: ");
            model.OnNext(this);
        }else{
            Log.e(TAG, "Account is Error: ");
        }
    }
}
public class Model implements Contract.Model{
    private static String TAG = "Model";
    private APIService apiService = SiteManager.getInstance().getAPI();
    @Override
    public void OnNext(Contract.Model.FinishListener OnFinished) {
        GetFakeAPI(OnFinished);
    }
    public void GetFakeAPI(Contract.Model.FinishListener OnFinished){
        Call<List<APIResponse>> call = apiService.response ();
        call.enqueue (new Callback<List<APIResponse>>() {
            @Override
            public void onResponse (Call<List<APIResponse>> call, Response<List<APIResponse>> response) {
//                for (int i = 0;i<response.body ().size ();i++){
//                    Log.e (TAG, "userid: "+response.body ().get (i).getUserId ());
//                    Log.e (TAG, "ID: "+response.body ().get (i).getId ());
//                    Log.e (TAG, "title: "+response.body ().get (i).getTitle ());
//                    Log.e (TAG, "body: "+response.body ().get (i).getBody ());
//                }
//                Log.e (TAG, "ToString Size = "+response.body().toString());
                OnFinished.OnFinished(response.body().toString());
            }
            @Override
            public void onFailure (Call<List<APIResponse>> call, Throwable t) {
                Log.e (TAG, "onFailure: " );
            }
        });
    }
}
這邊的Model撰寫方式與上面的GetFakeAPI一樣是寫在副程式並套入到OnNext中。
    public void GetObservableResponse(Contract.Model.FinishListener OnFinished){
        apiService.observableResponse()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableObserver<Response<List<APIResponse>>>() {
                    @Override
                    public void onNext(@NonNull Response<List<APIResponse>> listResponse) {
//                        for(int i = 0;i<listResponse.body().size();i++){
//                            Log.e(TAG, "onNextId: "+listResponse.body().get(i).getId() );
//                            Log.e(TAG, "onNextUserId: "+listResponse.body().get(i).getUserId() );
//                            Log.e(TAG, "onNextTitle: "+listResponse.body().get(i).getTitle() );
//                            Log.e(TAG, "onNextBody: "+listResponse.body().get(i).getBody() );
//                        }
                        Log.e(TAG, "onNext_Observable: ");
                        OnFinished.OnFinished(listResponse.body().toString());
                    }
                    @Override
                    public void onError(@NonNull Throwable e) {
                        Log.e(TAG, "onError: "+e );
                    }
                    @Override
                    public void onComplete() {
                        Log.e(TAG, "已完成資料接收 ");
                    }
                });
    }