Blog Tutorial Android Bagi Pemula

Sunday, February 21, 2021

Aplikasi Movie & TV Show Menggunakan API TMDB (Part 3: Kelanjutan dari part 2)

UPDATE ! 10 Juli 2021. Penambahan repositori Github, dapat dilihat di https://github.com/DaltrayNababan/MovieTracker


Untuk kembali ke tutorial bagian 2 silahkan KLIK DISINI

Pada tutorial bagian 2, terakhir kita membuat 2 buah layout resource files untuk layout movie dan tv, selanjutnya kedua layout tersebut akan kita include ke activity_main.xml. Berikut isi dari activity_main.xml.

activity_main.xml :
<?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">

<LinearLayout
android:id="@+id/layoutActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_actionbar"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp"
app:layout_constraintTop_toTopOf="parent">

<TextView
android:id="@+id/textAppTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />

<ImageView
android:id="@+id/imageSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_oval"
android:contentDescription="@string/app_name"
android:padding="3dp"
android:src="@drawable/ic_search" />

</LinearLayout>

<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/layoutActionBar">

<LinearLayout
android:id="@+id/layoutContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">

<include layout="@layout/layout_movie" />

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:background="@color/black" />

<include layout="@layout/layout_tv" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:alpha="0.3"
android:autoLink="web"
android:gravity="center"
android:padding="15dp"
android:text="@string/text_info"
android:textColor="@color/black"
android:textSize="18sp" />

</LinearLayout>

</androidx.core.widget.NestedScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>


Selanjutnya kita implementasi di MainActivity.java untuk mulai menampilkan Most Popular Movies, Now Playing Movies, Upcoming Movies, Top Rated Movies, Most Popular TV Shows, Top Rated TV Shows dan On Air TV Shows.

Isi file ini cukup panjang, mencapai hampir 500 lines termasuk import class. Class / library Retrofit kita gunakan disini untuk memperoleh data movie dan tv dari database TMDB, juga nantinya pada aktivitas pencarian dan aktivitas rincian. Karena isi class ini panjang, maka box coding area saya buat mode scrolling.

MainActivity.java :
package com.gwnbs.movietracker;

import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

/**
*Created by : Daltray Nababan
* site : https://www.gwnbs.com
* email : birwinecheese@gmail.com
*/

public class MainActivity extends AppCompatActivity {

private ApiService apiService;
private RecyclerView rvMoviePopular, rvMovieNowPlaying, rvMovieTopRated, rvMovieUpcoming;
private ProgressBar loadingMoviePopular, loadingMovieNowPlaying, loadingMovieTopRated, loadingMovieUpcoming;
private ProgressBar loadingMainMoviePopular, loadingMainMovieNowPlaying, loadingMainMovieTopRated, loadingMainMovieUpcoming;
private MovieAdapter moviePopularAdapter, movieNowPlayingAdapter, movieUpcomingAdapter, movieTopRatedAdapter;
private final List<MovieResult> moviePopularResults = new ArrayList<>();
private final List<MovieResult> movieNowPlayingResults = new ArrayList<>();
private final List<MovieResult> movieUpcomingResults = new ArrayList<>();
private final List<MovieResult> movieTopRatedResults = new ArrayList<>();
private int currentPageMoviePopular = 1, currentPageMovieNowPlaying = 1,
currentPageMovieUpcoming = 1, currentPageMovieTopRated = 1;
private int totalPagesMoviePopular = 1, totalPagesMovieNowPlaying = 1, totalPagesMovieUpcoming =1,
totalPagesMovieTopRated = 1;

private RecyclerView rvTvPopular, rvTvTopRated, rvTvOnAir;
private ProgressBar loadingTvPopular, loadingTvTopRated, loadingTvOnAir;
private ProgressBar loadingMainTvPopular, loadingMainTvTopRated, loadingMainTvOnAir;
private TVAdapter tvPopularAdapter, tvTopRatedAdapter, tvOnAirAdapter;
private final List<TVResult> tvPopularResults = new ArrayList<>();
private final List<TVResult> tvTopRatedResults = new ArrayList<>();
private final List<TVResult> tvOnAirResults = new ArrayList<>();
private int currentPageTVPopular = 1, currentPageTVTopRated = 1, currentPageTVOnAir = 1;
private int totalPagesTVPopular = 1, totalPagesTVTopRated = 1, totalPagesTVOnAir = 1;

//Silahkan diganti dengan API Key TMDB Anda
public static final String MYAPI_KEY = "api_key_anda";

public static final String LANGUAGE = "en-US";
private String searchType = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Retrofit retrofit = ApiClient.getClient();
apiService = retrofit.create(ApiService.class);

setPopularMovies();
setNowPlayingMovies();
setUpcomingMovies();
setTopRatedMovies();

setPopularTV();
setTopRatedTV();
setOnAirTV();

findViewById(R.id.imageSearch).setOnClickListener(v -> dialogSearch());

}

private void setPopularMovies() {
rvMoviePopular = findViewById(R.id.rvMoviePopular);
moviePopularAdapter = new MovieAdapter(moviePopularResults, this);
loadingMoviePopular = findViewById(R.id.loadingMoviePopular);
loadingMainMoviePopular = findViewById(R.id.loadingMainMoviePopular);
loadingMainMoviePopular.setVisibility(View.VISIBLE);
getPopularMovies();
rvMoviePopular.setAdapter(moviePopularAdapter);

rvMoviePopular.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvMoviePopular.canScrollHorizontally(1)) {
loadingMoviePopular.setVisibility(View.VISIBLE);
if (currentPageMoviePopular <= totalPagesMoviePopular) {
currentPageMoviePopular += 1;
getPopularMovies();
}
}
}
});
}

private void getPopularMovies() {
Call<MovieRespon> call = apiService.getPopularMovies(MYAPI_KEY, LANGUAGE, currentPageMoviePopular);
call.enqueue(new Callback<MovieRespon>() {
@Override
public void onResponse(@NonNull Call<MovieRespon> call,@NonNull Response<MovieRespon> response) {
if (response.body() != null) {
totalPagesMoviePopular = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainMoviePopular.setVisibility(View.GONE);
loadingMoviePopular.setVisibility(View.GONE);
int oldCount = moviePopularResults.size();
moviePopularResults.addAll(response.body().getResults());
moviePopularAdapter.notifyItemChanged(oldCount, moviePopularResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<MovieRespon> call,@NonNull Throwable t) {
loadingMainMoviePopular.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat popular movies",
Toast.LENGTH_SHORT).show();
}
});
}

private void setNowPlayingMovies() {
rvMovieNowPlaying = findViewById(R.id.rvMovieNowPlaying);
movieNowPlayingAdapter = new MovieAdapter(movieNowPlayingResults, this);
loadingMovieNowPlaying = findViewById(R.id.loadingMovieNowPlaying);
loadingMainMovieNowPlaying = findViewById(R.id.loadingMainMovieNowPlaying);
loadingMainMovieNowPlaying.setVisibility(View.VISIBLE);
getNowPlayingMovies();
rvMovieNowPlaying.setAdapter(movieNowPlayingAdapter);

rvMovieNowPlaying.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvMovieNowPlaying.canScrollHorizontally(1)) {
loadingMovieNowPlaying.setVisibility(View.VISIBLE);
if (currentPageMovieNowPlaying <= totalPagesMovieNowPlaying) {
currentPageMovieNowPlaying += 1;
getNowPlayingMovies();
}
}
}
});
}

private void getNowPlayingMovies() {
Call<MovieRespon> call = apiService.getNowPlayingMovies(MYAPI_KEY, LANGUAGE, currentPageMovieNowPlaying);
call.enqueue(new Callback<MovieRespon>() {
@Override
public void onResponse(@NonNull Call<MovieRespon> call,@NonNull Response<MovieRespon> response) {
if (response.body() != null) {
totalPagesMovieNowPlaying = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainMovieNowPlaying.setVisibility(View.GONE);
loadingMovieNowPlaying.setVisibility(View.GONE);
int oldCount = movieNowPlayingResults.size();
movieNowPlayingResults.addAll(response.body().getResults());
movieNowPlayingAdapter.notifyItemChanged(oldCount, movieNowPlayingResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<MovieRespon> call,@NonNull Throwable t) {
loadingMainMovieNowPlaying.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat now playing movies",
Toast.LENGTH_SHORT).show();
}
});
}

private void setUpcomingMovies() {
rvMovieUpcoming = findViewById(R.id.rvUpcomingMovie);
movieUpcomingAdapter = new MovieAdapter(movieUpcomingResults, this);
loadingMovieUpcoming = findViewById(R.id.loadingMovieUpcoming);
loadingMainMovieUpcoming = findViewById(R.id.loadingMainMovieUpcoming);
loadingMainMovieUpcoming.setVisibility(View.VISIBLE);
getUpcomingMovies();
rvMovieUpcoming.setAdapter(movieUpcomingAdapter);

rvMovieUpcoming.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvMovieUpcoming.canScrollHorizontally(1)) {
loadingMovieUpcoming.setVisibility(View.VISIBLE);
if (currentPageMovieUpcoming <= totalPagesMovieUpcoming) {
currentPageMovieUpcoming += 1;
getUpcomingMovies();
}
}
}
});
}

private void getUpcomingMovies() {
Call<MovieRespon> call = apiService.getUpcomingMovies(MYAPI_KEY, LANGUAGE, currentPageMovieUpcoming);
call.enqueue(new Callback<MovieRespon>() {
@Override
public void onResponse(@NonNull Call<MovieRespon> call,@NonNull Response<MovieRespon> response) {
if (response.body() != null) {
totalPagesMovieUpcoming = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainMovieUpcoming.setVisibility(View.GONE);
loadingMovieUpcoming.setVisibility(View.GONE);
int oldCount = movieUpcomingResults.size();
movieUpcomingResults.addAll(response.body().getResults());
movieUpcomingAdapter.notifyItemChanged(oldCount, movieUpcomingResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<MovieRespon> call,@NonNull Throwable t) {
loadingMainMovieUpcoming.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat upcoming movies",
Toast.LENGTH_SHORT).show();
}
});
}

private void setTopRatedMovies() {
rvMovieTopRated = findViewById(R.id.rvMovieTopRated);
movieTopRatedAdapter = new MovieAdapter(movieTopRatedResults, this);
loadingMovieTopRated = findViewById(R.id.loadingMovieTopRated);
loadingMainMovieTopRated = findViewById(R.id.loadingMainMovieTopRated);
loadingMainMovieTopRated.setVisibility(View.VISIBLE);
getTopRatedMovies();
rvMovieTopRated.setAdapter(movieTopRatedAdapter);

rvMovieTopRated.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvMovieTopRated.canScrollHorizontally(1)) {
loadingMovieTopRated.setVisibility(View.VISIBLE);
if (currentPageMovieTopRated <= totalPagesMovieTopRated) {
currentPageMovieTopRated += 1;
getTopRatedMovies();
}
}
}
});
}

private void getTopRatedMovies() {
Call<MovieRespon> call = apiService.getTopRatedMovies(MYAPI_KEY, LANGUAGE, currentPageMovieTopRated);
call.enqueue(new Callback<MovieRespon>() {
@Override
public void onResponse(@NonNull Call<MovieRespon> call,@NonNull Response<MovieRespon> response) {
if (response.body() != null) {
totalPagesMovieTopRated = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainMovieTopRated.setVisibility(View.GONE);
loadingMovieTopRated.setVisibility(View.GONE);
int oldCount = movieTopRatedResults.size();
movieTopRatedResults.addAll(response.body().getResults());
movieTopRatedAdapter.notifyItemChanged(oldCount, movieTopRatedResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<MovieRespon> call,@NonNull Throwable t) {
loadingMainMovieTopRated.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat top rated movies",
Toast.LENGTH_SHORT).show();
}
});
}

private void setPopularTV() {
rvTvPopular = findViewById(R.id.rvTvPopular);
tvPopularAdapter = new TVAdapter(tvPopularResults, this);
loadingTvPopular = findViewById(R.id.loadingTvPopular);
loadingMainTvPopular = findViewById(R.id.loadingMainTvPopular);
loadingMainTvPopular.setVisibility(View.VISIBLE);
getPopularTV();
rvTvPopular.setAdapter(tvPopularAdapter);

rvTvPopular.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvTvPopular.canScrollHorizontally(1)) {
loadingTvPopular.setVisibility(View.VISIBLE);
if (currentPageTVPopular <= totalPagesTVPopular) {
currentPageTVPopular += 1;
getPopularTV();
}
}
}
});
}

private void getPopularTV() {
Call<TVRespon> call = apiService.getTvPopular(MYAPI_KEY, LANGUAGE, currentPageTVPopular);
call.enqueue(new Callback<TVRespon>() {
@Override
public void onResponse(@NonNull Call<TVRespon> call,@NonNull Response<TVRespon> response) {
if (response.body() != null) {
totalPagesTVPopular = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainTvPopular.setVisibility(View.GONE);
loadingTvPopular.setVisibility(View.GONE);
int oldCount = tvPopularResults.size();
tvPopularResults.addAll(response.body().getResults());
tvPopularAdapter.notifyItemChanged(oldCount, tvPopularResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<TVRespon> call,@NonNull Throwable t) {
loadingMainTvPopular.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat popular tv shows",
Toast.LENGTH_SHORT).show();
}
});
}

private void setTopRatedTV() {
rvTvTopRated = findViewById(R.id.rvTvTopRated);
tvTopRatedAdapter = new TVAdapter(tvTopRatedResults, this);
loadingTvTopRated = findViewById(R.id.loadingTvTopRated);
loadingMainTvTopRated = findViewById(R.id.loadingMainTvTopRated);
loadingMainTvTopRated.setVisibility(View.VISIBLE);
getTopRatedTV();
rvTvTopRated.setAdapter(tvTopRatedAdapter);

rvTvTopRated.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvTvTopRated.canScrollHorizontally(1)) {
loadingTvTopRated.setVisibility(View.VISIBLE);
if (currentPageTVTopRated <= totalPagesTVTopRated) {
currentPageTVTopRated += 1;
getTopRatedTV();
}
}
}
});
}

private void getTopRatedTV() {
Call<TVRespon> call = apiService.getTvTopRated(MYAPI_KEY, LANGUAGE, currentPageTVTopRated);
call.enqueue(new Callback<TVRespon>() {
@Override
public void onResponse(@NonNull Call<TVRespon> call,@NonNull Response<TVRespon> response) {
if (response.body() != null) {
totalPagesTVTopRated = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingTvTopRated.setVisibility(View.GONE);
loadingMainTvTopRated.setVisibility(View.GONE);
int oldCount = tvTopRatedResults.size();
tvTopRatedResults.addAll(response.body().getResults());
tvTopRatedAdapter.notifyItemChanged(oldCount, tvTopRatedResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<TVRespon> call,@NonNull Throwable t) {
loadingMainTvTopRated.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat top rated tv shows",
Toast.LENGTH_SHORT).show();
}
});
}

private void setOnAirTV() {
rvTvOnAir = findViewById(R.id.rvTvOnAir);
tvOnAirAdapter = new TVAdapter(tvOnAirResults, this);
loadingTvOnAir = findViewById(R.id.loadingTvOnAir);
loadingMainTvOnAir = findViewById(R.id.loadingMainTvOnAir);
loadingMainTvOnAir.setVisibility(View.VISIBLE);
getOnAirTV();
rvTvOnAir.setAdapter(tvOnAirAdapter);

rvTvOnAir.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvTvOnAir.canScrollHorizontally(1)) {
loadingTvOnAir.setVisibility(View.VISIBLE);
if (currentPageTVOnAir <= totalPagesTVOnAir) {
currentPageTVOnAir += 1;
getOnAirTV();
}
}
}
});
}

private void getOnAirTV() {
Call<TVRespon> call = apiService.getTvOnAir(MYAPI_KEY, LANGUAGE, currentPageTVOnAir);
call.enqueue(new Callback<TVRespon>() {
@Override
public void onResponse(@NonNull Call<TVRespon> call,@NonNull Response<TVRespon> response) {
if (response.body() != null) {
totalPagesTVOnAir = response.body().getTotalPages();
if (response.body().getResults() != null) {
loadingMainTvOnAir.setVisibility(View.GONE);
loadingTvOnAir.setVisibility(View.GONE);
int oldCount = tvOnAirResults.size();
tvOnAirResults.addAll(response.body().getResults());
tvOnAirAdapter.notifyItemChanged(oldCount, tvOnAirResults.size());
}
}
}

@Override
public void onFailure(@NonNull Call<TVRespon> call,@NonNull Throwable t) {
loadingMainTvOnAir.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat on air tv shows",
Toast.LENGTH_SHORT).show();
}
});
}

private void dialogSearch() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View v = inflater.inflate(R.layout.dialog_search, null);

EditText inputSearch = v.findViewById(R.id.inputSearch);
ImageView imageDoSearch = v.findViewById(R.id.imageDoSearch);
RadioGroup radioGroup = v.findViewById(R.id.radioGroup);
RadioButton radioButtonMovie = v.findViewById(R.id.radioButtonMovie);
RadioButton radioButtonTv = v.findViewById(R.id.radioButtonTv);

builder.setView(v);
AlertDialog dialogSearch = builder.create();
if (dialogSearch.getWindow() != null)
dialogSearch.getWindow().setBackgroundDrawable(new ColorDrawable(0));

radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.radioButtonMovie) {
searchType = radioButtonMovie.getText().toString();
} else {
searchType = radioButtonTv.getText().toString();
}
});
imageDoSearch.setOnClickListener(view -> doSearch(inputSearch.getText().toString()));

inputSearch.setOnEditorActionListener((v1, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_GO) {
doSearch(inputSearch.getText().toString());
}
return false;
});

dialogSearch.show();
}

private void doSearch(String query) {
if (query.isEmpty()) {
Toast.makeText(getApplicationContext(), "Tidak ada huruf terdeteksi",
Toast.LENGTH_SHORT).show();
return;
}
if (searchType == null) {
Toast.makeText(getApplicationContext(), "Harap pilih antara tipe movie dan tv",
Toast.LENGTH_SHORT).show();
return;
}
Intent i = new Intent(MainActivity.this, SearchActivity.class);
i.putExtra("tipe", searchType);
i.putExtra("searchFor", query);
startActivity(i);
}
}


Silahkan untuk mengganti nilai String MYAPI_KEY dengan API Key TMDB Anda. Karena disini kita sudah menggunakan Java versi 1.8 sehingga untuk eksekusi metode listener seperti click tidak lagi diperlukan override public onClick(View v), semua metode listener dapat digantikan dengan yang namanya "Lambda Expression (->)".

Pada code MainActivity diatas, Anda akan mendapatkan error untuk dialog_search.xml dan Intent menuju SearchActivity class karena memang layout dan activity nya belum kita buat, silahkan di abaikan untuk sementara karena kita akan membuat terlebih dahulu activity details. Silahkan buat empty activity baru dengan nama DetailsActivity.java dan layoutnya activity_details.xml.

Disini kita akan menampilkan beberapa details mengenai movie / tv, sekitar 16 nilai rincian termasuk gambar poster dan gambar backdrop. Details untuk movie dan tv berada dalam satu activity saja yakni DetailsActivity. Disini kita menggunakan statement untuk bergantian antara details movie atau tv, kita melacak nya dengan mengirimkan nilai Intent extra berbeda. Baik, berikut isi file layout dan java class ini.

activity_details.xml :
<?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=".DetailsActivity">

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.1">

<ImageView
android:id="@+id/imagePosterBack"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/app_name"
android:visibility="gone" />

</FrameLayout>

<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageBackdrop"
android:layout_width="match_parent"
android:layout_height="255dp"
android:layout_margin="1dp"
app:layout_constraintTop_toTopOf="parent"
app:riv_corner_radius="4dp" />

<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imagePoster"
android:layout_width="150dp"
android:layout_height="220dp"
android:layout_marginStart="10dp"
app:layout_constraintBottom_toBottomOf="@id/imageBackdrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageBackdrop"
app:riv_corner_radius="6dp" />

<View
android:layout_width="0dp"
android:layout_height="40dp"
android:background="@drawable/bg_view_gradient"
app:layout_constraintStart_toEndOf="@id/imagePoster"
app:layout_constraintTop_toTopOf="@id/imagePoster"
app:layout_constraintBottom_toBottomOf="@id/imagePoster"/>

<LinearLayout
android:id="@+id/layoutMainDetails"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imagePoster"
app:layout_constraintTop_toBottomOf="@id/imageBackdrop">

<TextView
android:id="@+id/textTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/black"
android:textSize="30sp"
android:textStyle="bold" />

<TextView
android:id="@+id/textRuntime"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="22sp" />

<TextView
android:id="@+id/textReleaseDate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="22sp" />

</LinearLayout>

<LinearLayout
android:id="@+id/layoutOtherDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layoutMainDetails">

<TextView
android:id="@+id/textOverview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.6"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="18sp" />

<TextView
android:id="@+id/textlanguage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textStatus"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textBudgetOrSeasons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textRevenueOrEpisodes"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textPopularity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textTagline"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textVoteCount"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textVoteAverage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/textHomepage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:autoLink="web"
android:includeFontPadding="false"
android:textColor="@color/black"
android:textSize="20sp" />

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.core.widget.NestedScrollView>

<ProgressBar
android:id="@+id/loadingDetails"
android:layout_width="70dp"
android:layout_height="70dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/imageBackDetails"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_back"
android:padding="3dp"
android:layout_marginStart="10dp"
android:layout_marginTop="15dp"
android:background="@drawable/bg_oval"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

DetailsActivity.java :
package com.gwnbs.movietracker;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat;
import androidx.core.widget.NestedScrollView;

import com.makeramen.roundedimageview.RoundedImageView;

import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Locale;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
*Created by : Daltray Nababan
* site : https://www.gwnbs.com
* email : birwinecheese@gmail.com
*/

public class DetailsActivity extends AppCompatActivity {

private RoundedImageView imageBackdrop, imagePoster;
private ImageView imagePosterBack;
private TextView textTitle, textRuntime, textReleaseDate, textOverview, textlanguage, textStatus, textBudgetOrSeasons, textRevenueOrEpisodes,
textPopularity, textTagline, textVoteCount, textVoteAverage, textHomepage;
private ProgressBar loadingDetails;
private NestedScrollView scrollView;
private int id;
private ApiService apiService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);

imagePosterBack = findViewById(R.id.imagePosterBack);
imageBackdrop = findViewById(R.id.imageBackdrop);
imagePoster = findViewById(R.id.imagePoster);
textTitle = findViewById(R.id.textTitle);
textRuntime = findViewById(R.id.textRuntime);
textReleaseDate = findViewById(R.id.textReleaseDate);
textOverview = findViewById(R.id.textOverview);
textlanguage = findViewById(R.id.textlanguage);
textStatus = findViewById(R.id.textStatus);
textBudgetOrSeasons = findViewById(R.id.textBudgetOrSeasons);
textRevenueOrEpisodes = findViewById(R.id.textRevenueOrEpisodes);
textPopularity = findViewById(R.id.textPopularity);
textTagline = findViewById(R.id.textTagline);
textVoteCount = findViewById(R.id.textVoteCount);
textVoteAverage = findViewById(R.id.textVoteAverage);
textHomepage = findViewById(R.id.textHomepage);
loadingDetails = findViewById(R.id.loadingDetails);
scrollView = findViewById(R.id.scrollView);

apiService = ApiClient.getClient().create(ApiService.class);

id = getIntent().getIntExtra("id", 0);
String tipe = getIntent().getStringExtra("tipe");
switch (tipe) {
case "movie":
setMovieDetails();
break;
case "tv":
setTVDetails();
break;
}

findViewById(R.id.imageBackDetails).setOnClickListener(v -> onBackPressed());
}

private void setMovieDetails() {
loadingDetails.setVisibility(View.VISIBLE);
Call<MovieDetails> call = apiService.getMovieDetails(String.valueOf(id), MainActivity.MYAPI_KEY);
call.enqueue(new Callback<MovieDetails>() {
@Override
public void onResponse(@NonNull Call<MovieDetails> call, @NonNull Response<MovieDetails> response) {
if (response.body() != null) {
loadingDetails.setVisibility(View.GONE);
scrollView.setVisibility(View.VISIBLE);
imagePosterBack.setVisibility(View.VISIBLE);
ImageAdapter.setPosterURL(imagePosterBack, response.body().getPosterPath());
ImageAdapter.setBackdropURL(imageBackdrop, response.body().getBackdropPath());
ImageAdapter.setPosterURL(imagePoster, response.body().getPosterPath());
textTitle.setText(response.body().getTitle());
setHTMLText(textRuntime, "Runtime", response.body().getRuntime() + " minutes");
setHTMLText(textReleaseDate, "Released on", response.body().getReleaseDate());
textOverview.setText(response.body().getOverview());
setHTMLText(textlanguage, "Language", response.body().getLanguage());
setHTMLText(textStatus, "Status", response.body().getStatus());

Double budget = Double.parseDouble(response.body().getBudget());
String budgetFormatted = NumberFormat.getCurrencyInstance(Locale.US).format(budget);
setHTMLText(textBudgetOrSeasons, "Budget", budgetFormatted);

Double revenue = Double.parseDouble(response.body().getRevenue());
String revenueFormatted = NumberFormat.getCurrencyInstance(Locale.US).format(revenue);
setHTMLText(textRevenueOrEpisodes, "Revenue", revenueFormatted);

setHTMLText(textPopularity, "Popularity", response.body().getPopularity());
setHTMLText(textTagline, "Tagline", response.body().getTagline());
setHTMLText(textVoteCount, "Vote Count", response.body().getVoteAverage());
setHTMLText(textVoteAverage, "Vote Average", response.body().getVoteCount());
setHTMLText(textHomepage, "Homepage", response.body().getHomepage());
}
}

@Override
public void onFailure(@NonNull Call<MovieDetails> call, @NonNull Throwable t) {
loadingDetails.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat details dari " + id,
Toast.LENGTH_SHORT).show();
}
});
}

private void setTVDetails() {
loadingDetails.setVisibility(View.VISIBLE);
Call<TVDetails> call = apiService.getTvDetails(String.valueOf(id), MainActivity.MYAPI_KEY);
call.enqueue(new Callback<TVDetails>() {
@Override
public void onResponse(@NonNull Call<TVDetails> call,@NonNull Response<TVDetails> response) {
if (response.body() != null) {
loadingDetails.setVisibility(View.GONE);
scrollView.setVisibility(View.VISIBLE);
imagePosterBack.setVisibility(View.VISIBLE);
ImageAdapter.setPosterURL(imagePosterBack, response.body().getPosterPath());
ImageAdapter.setBackdropURL(imageBackdrop, response.body().getBackdropPath());
ImageAdapter.setPosterURL(imagePoster, response.body().getPosterPath());
textTitle.setText(response.body().getName());

String runtime = Arrays.toString(response.body().getEpisodeRuntime());
runtime = runtime.replace("[", "");
runtime = runtime.replace("]", "");
runtime = runtime.replace(",", " &");
setHTMLText(textRuntime, "Runtime", runtime + " min");

textReleaseDate.setText(HtmlCompat.fromHtml("<font color='#0B6A10'>First air date</font> : " +
response.body().getFirstAirDate() + "<br/><font color='#0B6A10'>Last air date</font> : " +
response.body().getLastAirdate() , HtmlCompat.FROM_HTML_MODE_LEGACY));

textOverview.setText(response.body().getOverview());
setHTMLText(textlanguage, "Language", response.body().getOriginalLanguage());
setHTMLText(textStatus, "Status", response.body().getStatus());
setHTMLText(textBudgetOrSeasons, "Seasons", response.body().getNumberOfSeasons());
setHTMLText(textRevenueOrEpisodes, "Episodes", response.body().getNumberOfEpisodes());
setHTMLText(textPopularity, "Popularity", response.body().getPopularity());
setHTMLText(textTagline, "Tagline", response.body().getTagline());
setHTMLText(textVoteCount, "Vote Count", response.body().getVoteAverage());
setHTMLText(textVoteAverage, "Vote Average", response.body().getVoteCount());
setHTMLText(textHomepage, "Homepage", response.body().getHomepage());
}
}

@Override
public void onFailure(@NonNull Call<TVDetails> call,@NonNull Throwable t) {
loadingDetails.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "Terjadi kesalahan saat memuat details dari " + id,
Toast.LENGTH_SHORT).show();
}
});
}

private void setHTMLText(TextView tv, String stringColored, String stringValue) {
tv.setText(HtmlCompat.fromHtml("<font color='#0B6A10'>" + stringColored + "</font> : " + stringValue,
HtmlCompat.FROM_HTML_MODE_LEGACY));
}
}


Implementasi terakhir yang akan kita aplikasikan adalah pencarian movie dan tv. Untuk query pencarian dan tipe kita terapkan dalam sebuah dialog menggunakan AlertDialog pada MainActivity.java sebelumnya, kemudian kita kirimkan menggunakan Intent extra ke activity pencarian.

Baik silahkan buat terlebih dahulu sebuah resource file untuk dialog dengan nama dialog_search.xml kemudian buat empty activty baru dengan nama class SearchActivity.java dan layoutnya activity_search.xml. Hasil pencarian (item-item) akan kita tampilkan menggunakan RecyclerView dengan layout manager StaggeredGridLayout 4 kolom. Berikut selengkapnya :

dialog_search.xml :
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@drawable/bg_text_title"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="15dp"
app:layout_constraintTop_toTopOf="parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/search_movie_or_tv_show"
android:textColor="@color/black"
android:textSize="22sp" />

<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/white"
android:orientation="horizontal">

<RadioButton
android:id="@+id/radioButtonMovie"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/movies"
android:textColor="@color/black"
android:textSize="20sp" />

<RadioButton
android:id="@+id/radioButtonTv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/tv_shows"
android:textColor="@color/black"
android:textSize="20sp" />

</RadioGroup>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginBottom="10dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp">

<EditText
android:id="@+id/inputSearch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="@string/enter_keyword"
android:imeOptions="actionGo"
android:importantForAutofill="no"
android:inputType="text"
android:padding="5dp"
android:textColor="@color/black"
android:textSize="20sp" />

<ImageView
android:id="@+id/imageDoSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:background="@drawable/bg_oval"
android:contentDescription="@string/app_name"
android:padding="3dp"
android:src="@drawable/ic_search" />

</LinearLayout>

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

activity_search.xml :
<?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=".SearchActivity">

<TextView
android:id="@+id/textSearchQuery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:paddingStart="60dp"
android:paddingEnd="0dp"
android:background="@color/color_actionbar"
android:gravity="center_vertical"
android:textColor="@color/black"
android:textSize="22sp"
app:layout_constraintTop_toTopOf="parent"/>

<ImageView
android:id="@+id/imageBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_back"
android:padding="3dp"
android:layout_marginStart="10dp"
android:background="@drawable/bg_oval"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="@id/textSearchQuery"
app:layout_constraintTop_toTopOf="@id/textSearchQuery"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSearch"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="100dp"
android:clipToPadding="false"
app:layout_constraintTop_toBottomOf="@id/textSearchQuery"
app:layout_constraintBottom_toBottomOf="parent"/>

<ProgressBar
android:id="@+id/loadingSearch"
android:layout_width="70dp"
android:layout_height="70dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/textNoResults"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
android:textColor="@color/black"
android:text="@string/no_results"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<ProgressBar
android:id="@+id/loadingMoreSearch"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="20dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

SearchActivity.java :
package com.gwnbs.movietracker;

import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
*Created by : Daltray Nababan
* site : https://www.gwnbs.com
* email : birwinecheese@gmail.com
*/

public class SearchActivity extends AppCompatActivity {

private final List<MovieResult> movieResults = new ArrayList<>();
private final List<TVResult> TVResults = new ArrayList<>();
private String query;
private RecyclerView rvSearch;
private MovieSearchAdapter movieAdapter;
private TVSearchAdapter tvAdapter;
private ApiService apiService;
private ProgressBar loadingSearch, loadingMoreSearch;
private TextView textNoResults;
private int currentPage = 1;
private int totalPages = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);

loadingSearch = findViewById(R.id.loadingSearch);
loadingMoreSearch = findViewById(R.id.loadingMoreSearch);
textNoResults = findViewById(R.id.textNoResults);
TextView textSearchQuery = findViewById(R.id.textSearchQuery);
rvSearch = findViewById(R.id.rvSearch);
rvSearch.setLayoutManager(new StaggeredGridLayoutManager(4, RecyclerView.VERTICAL));
movieAdapter = new MovieSearchAdapter(movieResults, this);
tvAdapter = new TVSearchAdapter(TVResults, this);
loadingSearch.setVisibility(View.VISIBLE);

apiService = ApiClient.getClient().create(ApiService.class);

query = getIntent().getStringExtra("searchFor");
textSearchQuery.setText(HtmlCompat.fromHtml("You searched for : <b>" + query + "</b>",
HtmlCompat.FROM_HTML_MODE_LEGACY));
String tipe = getIntent().getStringExtra("tipe");
switch (tipe) {
case "Movies" :
searchForMovies();
rvSearch.setAdapter(movieAdapter);
break;
case "TV Shows" :
searchForTV();
rvSearch.setAdapter(tvAdapter);
break;
}

rvSearch.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!rvSearch.canScrollVertically(1)) {
if (currentPage <= totalPages) {
loadingMoreSearch.setVisibility(View.VISIBLE);
currentPage += 1;
if (tipe.equals("Movies"))
searchForMovies();
else searchForTV();
}
}
}
});

findViewById(R.id.imageBack).setOnClickListener(v -> onBackPressed());
}

private void searchForMovies() {
Call<MovieRespon> call = apiService.searchMovie(MainActivity.MYAPI_KEY, MainActivity.LANGUAGE,
query, currentPage);
call.enqueue(new Callback<MovieRespon>() {
@Override
public void onResponse(@NonNull Call<MovieRespon> call,@NonNull Response<MovieRespon> response) {
if (response.body() != null) {
if (response.body().getResults().size() > 0) {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
totalPages = response.body().getTotalPages();
int oldCount = movieResults.size();
movieResults.addAll(response.body().getResults());
movieAdapter.notifyItemRangeInserted(oldCount, movieResults.size());
checkSize(response.body().getResults().size());
} else {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(@NonNull Call<MovieRespon> call,@NonNull Throwable t) {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
textNoResults.setVisibility(View.VISIBLE);
textNoResults.setText(R.string.something_wrong);
}
});
}

private void searchForTV() {
Call<TVRespon> call = apiService.searchTv(MainActivity.MYAPI_KEY, MainActivity.LANGUAGE,
query, currentPage);
call.enqueue(new Callback<TVRespon>() {
@Override
public void onResponse(@NonNull Call<TVRespon> call,@NonNull Response<TVRespon> response) {
if (response.body() != null) {
if (response.body().getResults().size() > 0) {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
totalPages = response.body().getTotalPages();
int oldCount = TVResults.size();
TVResults.addAll(response.body().getResults());
tvAdapter.notifyItemRangeInserted(oldCount, TVResults.size());
checkSize(response.body().getResults().size());
} else {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(@NonNull Call<TVRespon> call,@NonNull Throwable t) {
loadingSearch.setVisibility(View.GONE);
loadingMoreSearch.setVisibility(View.GONE);
textNoResults.setVisibility(View.VISIBLE);
textNoResults.setText(R.string.something_wrong);
}
});
}

private void checkSize(int resulst) {
if (resulst == 0) {
textNoResults.setVisibility(View.VISIBLE);
} else {
textNoResults.setVisibility(View.GONE);
}
}
}


Perhatikan untuk import class, pastikan pada semua java class project Anda sama dengan yang ada di tutorial ini, karena bila salah import class bisa terjadi error dan bisa membuat Anda kebingungan. Hal ini dapat terjadi bila Anda tidak melakukan copy paste code dari postingan ini alias mengetik manual. Bila Anda copas code sudah dipastikan importnya sama dengan tutorial ini.

Nah terakhir tambahkan izi akses internet ke AndroidManifest.xml, kalau tidak apalikasi berpotensi crash dengan warning "akses ditolak, butuh internet permission".

AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.gwnbs.movietracker">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MovieTracker"
tools:ignore="AllowBackup">
<activity android:name=".SearchActivity"
android:screenOrientation="portrait"/>
<activity android:name=".DetailsActivity"
android:screenOrientation="portrait"/>
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


Nah, kita sudah clear. Bila Anda ingin menambah fitur-fitur lain, misalnya seperti video trailer movie / tv, daftar actor / actress, details actor / actress, movie / tv credit dan masih banyak lagi data lainnya yang bisa Anda request, silahkan mengunjungi Dokumentasi API TMDB.

Dan jangan lupa juga, bila Anda bersungguh-sungguh ingin mengembangkan aplikasi menggunakan API TMDB untuk dipublikasikan, silahkan membaca syarat dan ketentuan yang diberlakukan oleh TMDB, jangan sampai nantinya API Key dihapus karena terindikasi melanggar, tentunya aplikasi Anda tidak akan dapat di akses lagi alias crash setiap kali dibuka. S&K nya bisa dilihat DISINI.

Berikut screenshoots dari source dan resource project aplikasi ini, pastikan seluruh files ada dan sama.


Source files name of Movies & TV Shows App
Gambar 1 : Nama source files


Resources files name of Movies & TV Shows App
Gambar 2 : Nama resource files


Baiklah, bila Anda mengalami kesulitan bisa di sampaikan ke saya melalui komentar atau kontak email untuk fast respon melalui form email di bilah samping blog ini. Atau surfing google untuk yang lebih fast respon. Mungkin dari Anda sebagian ada yang merasa kalau saya kurang bersahabat bila dilihat dari gaya postingan, sebenarnya tidak! Saya suka membantu apalagi memiliki minat yang sama.

Sekian dan terimaksih untuk waktu dan kunjungannya.
Share:

0 comments:

Post a Comment

Hubungi Saya

Name

Email *

Message *

Terlaris 30 Hari Terakhir