iT邦幫忙

2023 iThome 鐵人賽

DAY 25
1

前言
這裡會教學大家怎麼使用Rxjava x Retrofit的方法。
功能
按下按鈕下會抓取資料,有進度條互動。



主畫面

main_activity

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
​
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是被查到的資料hihi"
        android:textSize="34sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.383" />
​
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="388dp"
        android:text="查詢"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
​
</androidx.constraintlayout.widget.ConstraintLayout>


網路的部分

  • 注意這裡是interface不是class
package com.example.rxjava_retorfit_2;
​
import java.util.List;
​
import io.reactivex.rxjava3.core.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
​
public interface jsonplaceholder {
    //拿取後段的網址 以'?'為界線
    //Observable<放入創立的class抓取資料>
    //notice: jsonplaceholder開頭資料是由list包起來的
    @GET("posts")
    Observable<List<jsonplaceholderdata>> getdata(
    );
}



解析資料的部分

package com.example.rxjava_retorfit_2;
​
public class jsonplaceholderdata {
​
    private int id;
​
    public int getId() {
        return id;
    }
}
​



主程式


MianActivity

package com.example.rxjava_retorfit_2;
​
import androidx.appcompat.app.AppCompatActivity;
​
​
import android.app.ProgressDialog;
import android.os.Bundle;
​
​
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
​
import java.util.List;
import java.util.concurrent.TimeUnit;
​
​
​
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
​
public class MainActivity extends AppCompatActivity {
    //設定URL
    private final String BASE_URL = "https://jsonplaceholder.typicode.com/";
    //宣告變數
    TextView data_Textview;
    Button query_button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
​
        //綁定元件
        ById();
​
        //查詢按鈕
        Query_button();
​
    }
​
    //查詢按鈕
    private void Query_button(){
        query_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //拿取jsonplaceholder 的資料與service連線
                getjsondata();
            }
        });
    }
    //拿取jsonplaceholder 的資料
    private void getjsondata(){
        ProgressDialog dialog_wait = new ProgressDialog(MainActivity.this); //網路延遲的對話框
        ProgressDialog dialog = new ProgressDialog(MainActivity.this);  //進度跑調的對話框
        //建立retorfit連線
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .baseUrl(BASE_URL) //設定基本URL
                .build();
        jsonplaceholder myjson_service = retrofit.create(jsonplaceholder.class);
​
​
        //notice 資料夾 app\manifests\AndroidManifest.xml
        //開頭需要放入網路權限<uses-permission android:name="android.permission.INTERNET" />
        //拿取service資料
        //解說函式 subscribeOn() : 我被觀察者(Observerable)被指定的路線是主程緒或副程序
        //解說函式 observeOn() : 我的觀察者也就是我的UI介面,顯示在主線程或副線程上
        //解說函式 subscribe() : 代表我訂閱的觀察者(也就是我的UI介面),且畫面會顯示在我指定的觀察者身上
        // AndroidSchedulers.mainThread() 主線程路線
        // Schedulers.io()  副線程路線
        myjson_service.getdata()
                .delay(2, TimeUnit.SECONDS) // 模擬網路延遲
                .subscribeOn(Schedulers.io())   //Schedulers.io() 如果有網路、檔案存取需求推薦使用,Rxjava 會幫我們管理 ThreadPool reuse 的部分。
                .observeOn(Schedulers.io()) // observeOn是指主畫面顯示 在()裡是 指在副線程執行回覆。
                .subscribe(new Observer<List<jsonplaceholderdata>>() { //訂閱
                    //初始化
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        Toast.makeText(MainActivity.this,"開始", Toast.LENGTH_SHORT).show();
                        dialog_wait.setTitle("進度");
                        dialog_wait.setMessage("等待中...");
                        dialog_wait.show(); //顯示網路延遲的對話框
                        SetMyProgress(dialog); //設定進度挑
                    }
                    //連線成功做動作
                    @Override
                    public void onNext(@NonNull List<jsonplaceholderdata> jsonplaceholderdata) {
                        Log.d("Title","請求成功");
                        dialog_wait.dismiss(); //關閉網路延遲對話框
                        runOnUiThread(()->{
                            dialog.show();  //顯示進度跑調的對話框
                        });
                        for(int i = 0; i < 10; i++){
                            int count = i;
                            int progressValue = (count + 1) * 10;
                            runOnUiThread(() -> {
                                //notice dialog.setProgress(progressValue); // 設定進度條的值 要放在runOnUiThread(()裡
                                //否則會發生更新數值沒有在UI畫面上
                                dialog.setProgress(progressValue); // 設定進度條的值
                                data_Textview.setText(Integer.toString(jsonplaceholderdata.get(count).getId()));
                            });
                            //當到達100就關閉進度挑
                            if(progressValue >= 100){
                                dialog.dismiss(); //關閉對話框
                            }
                            mydelay(); //自訂延遲打包程式碼看起來比較精簡
                        }
                    }
                    //連線失敗做動作
                    @Override
                    public void onError(@NonNull Throwable e) {
                        Log.d("Title","請求失敗");
                    }
                    //完成所有執行做動作
                    @Override
                    public void onComplete() {
                        runOnUiThread(() -> {
                            Toast.makeText(MainActivity.this,"完成", Toast.LENGTH_SHORT).show();
                        });
                    }
                });
    }
​
    //進度挑設定
    private void SetMyProgress(ProgressDialog dialog){
        dialog.setMessage("載入中...");
        dialog.setCancelable(false);//關閉
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//設置進度條樣式 - 水平
        dialog.setMax(100); // 設定進度條最大值
    }
    //綁定元件
    private void ById(){
        data_Textview = findViewById(R.id.textView);
        query_button = findViewById(R.id.button);
    }
    //用內建有的函數做延遲
    //notice 要做try AND catch 否則會報錯
    private void mydelay(){
        try{
            Thread.sleep(1000);
        }
        catch (Exception e){
            System.out.println("Error" + e);
        }
    }
}


程式碼解說

1.建立網路的部分

        //建立retorfit連線
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .baseUrl(BASE_URL) //設定基本URL
                .build();
        jsonplaceholder myjson_service = retrofit.create(jsonplaceholder.class);

Retrofit 是一個用於簡化和處理 HTTP 請求的庫,通常用於從網路服務中檢索數據。

  • addConverterFactory(GsonConverterFactory.create()):這裡配置了 Gson 作為 JSON 轉換器,用於處理 * HTTP 響應的 JSON 數據。
  • addCallAdapterFactory(RxJava3CallAdapterFactory.create()):這裡配置了 RxJava 3 作為呼叫適配器,用於處理 Retrofit 的呼叫和異步操作。
  • baseUrl(BASE_URL):這是指定基本 URL,它是您的 API 服務的根 URL。根據您的應用程式需要,您需要將 BASE_URL 替換為實際的 API URL。
  1. 請求連線的部分
myjson_service.getdata()
                .delay(2, TimeUnit.SECONDS) // 模擬網路延遲
                .subscribeOn(Schedulers.io())   //Schedulers.io() 如果有網路、檔案存取需求推薦使用,Rxjava 會幫我們管理 ThreadPool reuse 的部分。
                .observeOn(Schedulers.io()) // observeOn是指主畫面顯示 在()裡是 指在副線程執行回覆。
                .subscribe(new Observer<List<jsonplaceholderdata>>() { //訂閱
                    //初始化
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
​
                    }
                    //連線成功做動作
                    @Override
                    public void onNext(@NonNull List<jsonplaceholderdata> jsonplaceholderdata) {
​
                    }
                    //連線失敗做動作
                    @Override
                    public void onError(@NonNull Throwable e) {
                    
                    }
                    //完成所有執行做動作
                    @Override
                    public void onComplete() {
                    }
                });


-----總結-----
1.subscribeOn() :代表我訂閱的被觀察者是指定走主線程或副線程
2.observeOn() :代表我觀察者也就是我的主畫面UI指定的路線是主線程或副線程
3.subscribe() :這個函式代表我訂閱的觀察者(UI),會顯示畫面在我所指定的觀察者身上
4.各個函式內的線程的部分
Schedulers.io() : 副線程
AndroidSchedulers.mainThread() : 主線程


上一篇
Day24 - Rxjava x Retrofit 觀念篇
下一篇
Day26 - SharedPreferences 記住帳密
系列文
Android studio使用過程與開發說明30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言