close
Android網路三大框架為
1.okHttp
2.volley
3.retrofit
其中retrofit封裝okHttp,並且支援多種框架(Rxjava、LiveData...等等),連線速度也是其中最快的
這邊使用MVVM架構開始實作
第一步驟:在gradle引用Library
//retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
第二步驟:AndroidManifest.xml加入連網權限
<uses-permission android:name="android.permission.INTERNET" />
第三步驟:創建Retrofit物件來使用(這邊使用https://jsonplaceholder.typicode.com作為範例),並且使用okhttp的interceptor來做token和error的處理
class RetrofitManager { val URL = "https://jsonplaceholder.typicode.com/" fun getRetrofit(): Retrofit { return Retrofit.Builder() .baseUrl(URL) .addConverterFactory(GsonConverterFactory.create()) .client(getOkHttp())//add OkHttpClient .build() } fun getOkHttp(): OkHttpClient { val token = "RestfulApiToken" val okHttpBuilder = OkHttpClient.Builder() okHttpBuilder.addInterceptor { chain -> val apiRequest = chain.request() ////新增token到Header apiRequest.newBuilder().addHeader("Authorization","Bearer" + token) val apiResponse = chain.proceed(apiRequest) //處理Http error code when(apiResponse.code()){ 200 -> Log.d("test","success") 404 -> Log.d("test","fail") } apiResponse } return okHttpBuilder.build() } }
第四步驟:創建Api打回來的Json要轉換成的物件
data class AlbumsData(val userId:Int, val id:Int, val title:String)
第五步驟:創建Api連線介面
interface JsonApi { //https://jsonplaceholder.typicode.com/albums/1 @GET("albums/1") fun getAlbums(): Call<AlbumsData> //https://jsonplaceholder.typicode.com/albums/{id} @GET("albums/{id}") fun getAlbumsByIdFromPath(@Path("id") Id:Int): Call<AlbumsData> //https://jsonplaceholder.typicode.com/albums?postId={Id} @GET("albums") fun getAlbumsById(@Query("postId") Id:Int): Call<List<AlbumsData>> //post albumsData to https://jsonplaceholder.typicode.com @POST("albums") fun postAlbums(@Body albumsData: AlbumsData): Call<AlbumsData> }
第六步驟:在Repositoty用Retrofit物件打出Api
class ApiRepository { val jsonApi : JsonApi by lazy { RetrofitManager().getRetrofit().create(JsonApi::class.java) } fun getAllAlbums(): Call<AlbumsData>{ return jsonApi.getAlbums() } fun getAlbumsByIdFromPath(id:Int): Call<AlbumsData>{ return jsonApi.getAlbumsByIdFromPath(id) } fun getAlbumsById(id:Int): Call<List<AlbumsData>>{ return jsonApi.getAlbumsById(id) } fun postAlbums(albumsData:AlbumsData): Call<AlbumsData>{ return jsonApi.postAlbums(albumsData) } }
第七步驟:在ViewModel做Repository操作並將資料放入LiveData給Activity做觀察(記得不要在MainThread做網路同步操作)
class ApiViewModel : ViewModel() { private val albumsDataList = MutableLiveData<List<AlbumsData>>() val albumsLiveDataList: LiveData<List<AlbumsData>> = albumsDataList private val albumsData1 = MutableLiveData<AlbumsData>() val albumsLiveData1: LiveData<AlbumsData> = albumsData1 private val albumsData2 = MutableLiveData<AlbumsData>() val albumsLiveData2: LiveData<AlbumsData> = albumsData2 private val albumsData3 = MutableLiveData<AlbumsData>() val albumsLiveData3: LiveData<AlbumsData> = albumsData3 val apiRepository: ApiRepository by lazy { ApiRepository() } //同步執行 fun getAlbumSync() { Thread(Runnable { var apiResponse1 = apiRepository.getAlbumsById(1).execute() var apiResponse2 = apiRepository.getAlbumsByIdFromPath(2).execute() var apiResponse3 = apiRepository.getAllAlbums().execute() var apiResponse4 = apiRepository.postAlbums(AlbumsData(1, 1, "Castle on the Hill")).execute() if (isSuccess(apiResponse1)) { albumsDataList.postValue(apiResponse1.body()) } if (isSuccess(apiResponse2)) { albumsData1.postValue(apiResponse2.body()) } if (isSuccess(apiResponse3)) { albumsData2.postValue(apiResponse3.body()) } if (isSuccess(apiResponse4)) { albumsData3.postValue(apiResponse4.body()) } }).start() } //非同步執行 fun getAlbumAsync() { apiRepository.getAlbumsById(1).enqueue(object : Callback<List<AlbumsData>> { override fun onFailure(call: Call<List<AlbumsData>>, t: Throwable) { Log.d("test","Fail1") } override fun onResponse(call: Call<List<AlbumsData>>,response: Response<List<AlbumsData>>) { albumsDataList.value = response.body() } }) apiRepository.getAlbumsByIdFromPath(2).enqueue(object : Callback<AlbumsData>{ override fun onFailure(call: Call<AlbumsData>, t: Throwable) { Log.d("test","Fail2") } override fun onResponse(call: Call<AlbumsData>, response: Response<AlbumsData>) { albumsData1.value =response.body() } }) apiRepository.getAllAlbums().enqueue(object : Callback<AlbumsData>{ override fun onFailure(call: Call<AlbumsData>, t: Throwable) { Log.d("test","Fail3") } override fun onResponse(call: Call<AlbumsData>, response: Response<AlbumsData>) { albumsData2.value=response.body() } }) apiRepository.postAlbums(AlbumsData(1, 1, "Castle on the Hill")).enqueue(object : Callback<AlbumsData>{ override fun onFailure(call: Call<AlbumsData>, t: Throwable) { Log.d("test","Fail4") } override fun onResponse(call: Call<AlbumsData>, response: Response<AlbumsData>) { albumsData3.value=response.body() } }) } private fun <T> isSuccess(apiResponse: Response<T>): Boolean { return apiResponse.isSuccessful and (apiResponse.code() == 200) } }
第八步驟:Activity取得資料做使用
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val viewModel = ViewModelProvider(this).get(ApiViewModel::class.java) viewModel.getAlbum() viewModel.albumsLiveDataList.observe(this, Observer { Log.d("test","List:"+it.toString()) }) viewModel.albumsLiveData1.observe(this, Observer { Log.d("test","1:"+it.toString()) }) viewModel.albumsLiveData2.observe(this, Observer { Log.d("test","2:"+it.toString()) }) viewModel.albumsLiveData3.observe(this, Observer { Log.d("test","3:"+it.toString()) }) } }
全站熱搜
留言列表