Project introduction

Movie information App is a pure training project, using the system API28, all based on Androidx package. Developed in Kotlin language, using LiveData, ViewModel and Room in Android JetPack. In order to learn from Kotlin and consolidate custom views and Viewgroups, this project is to apply as little reliance on third-party libraries as possible. Api from Douban movie, douban movie Api is not public at present, xiaobian read in the brief book that someone exposed access to douban movie Api API_KEY, if there is violation, please contact delete!

Project screenshots

Screenshot 1 Screenshot 2 Screenshot 3 Screenshot 4 Screenshot of 5

The main knowledge points of APP design are as follows:

  • Material Design UI Design style;
  • Use Kotlin development, you want to learn and consolidate Kotlin, you can refer to this App;
  • Retrofit for LiveData handwriting a LiveDataCallAdapter adapter;
  • RecyclerView supports pull-up refresh and pull-down loading, and can add different types of header and bottom View and animation;
  • Support video playback

Look at a few pieces of code, access the core code of the network, design a lot of knowledge, this is the initiation of Retrofit

class RetrofitClient {
    companion object {
        val serviceApi: ServiceApi by lazy {
            val retrofitClient = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(OkHttpClient.Builder()
                            .addInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message ->
                                Log.i(TAG, message)
                            }).setLevel(HttpLoggingInterceptor.Level.BODY)
                            ).build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(LiveDataCallAdapterFactory())
                    .build()
            retrofitClient.create(ServiceApi::class.java)
        }
    }
}
Copy the code

Note that this code adds a LiveData data source adapter through factory mode

  .addCallAdapterFactory(LiveDataCallAdapterFactory())
Copy the code

Return an instance of LiveDataCallAdapter through the method factory and get the parameter types of the generic type

class LiveDataCallAdapterFactory : Factory() { override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? { val responseType: Type if (Factory.getRawType(returnType) ! = LiveData::class.java) { throw IllegalStateException("return type must be parameterized") } val observableType = Factory.getParameterUpperBound(0, returnType as ParameterizedType) val rawObservableType = Factory.getRawType(observableType) responseType = if (rawObservableType == Response::class.java) { if (observableType ! is ParameterizedType) { throw IllegalArgumentException("Response must be parameterized") } Factory.getParameterUpperBound(0, observableType) } else { observableType } return LiveDataCallAdapter<Any>(responseType) } }Copy the code

Notice the code in the adapt() method that converts Call to LiveData through the adapter pattern

class LiveDataCallAdapter<R>(private val responseType: Type) :
        CallAdapter<R, LiveData<R>> {
​
    override fun responseType() = responseType
​
    override fun adapt(call: Call<R>): LiveData<R> {
        return object : LiveData<R>() {
            private var started = AtomicBoolean(false)
            override fun onActive() {
                super.onActive()
                if (started.compareAndSet(false, true)) {
                    call.enqueue(object : Callback<R> {
                        override fun onResponse(call: Call<R>, response: Response<R>) {
                            postValue(response.body())
                        }
​
                        override fun onFailure(call: Call<R>, throwable: Throwable) {
                            postValue(null)
                        }
                    })
                }
            }
        }
    }
}
Copy the code

You may look at the code will be meng, I am looking at the code in the RxJava2CallAdapterFactory in RxJava2 would only write before, but the click to see the source code, in the analysis are different. An Observable is the equivalent of a LiveData. The adapt() method is eventually called by calling retrofitClient.create(ServiceApi::class.java).

Making portal