Tutorial Android: CRUD REST API Menggunakan Retrofit2 Dengan Java di Android Studio

Assalamualaikum bro, kali ini gue mau memberikan kalian-kalian tutorial nih bagaimana cara menerapkan CRUD request dari web service yang sudah di buat lalu di implementasikan di klien Android.
Hmmmmm … di pikir-pikir lagi bro, keknye gue jarang banget yak share tutorial di situs ini πŸ˜€ sepertinya tutorial perdana dah hahahaha … Sebelumnya kan gue share tutorial di situs lain yang berdomain renseo.blogspot.com πŸ˜€ . Ohh iya bro, untuk pembuatan rest apinya itu mungkin gue bahas di thread lain aja yak, tapi gue akan memberikan repo github gue yang terkait dengan pembuatan web servicenya, dan gue rest api itu menggunakan framework php yang bernama Codeigniter. Ya cari yang gampang-gampang ajalah untuk latihan CRUD request ini πŸ˜€ hahahaha …

HTTP Library yang gue pake untuk menerapkan CRUD request ini menggunakan Retrofit2. Kenapa pakai itu? Ya karena sudah nyaman dan menurut gue gak begitu sulit untuk pengkodean dsb lah πŸ˜€ . Permasalahan yang pernah gue temui untuk penggunaan library ini, kesalahan yang mereka lakukan kebanyakkan dari pembuatan pojonya doang bro, jadi pembuatan pojonya itu terkadang ada yang gak sesuai dengan struktur json yang sudah ada, lalu ada juga kesalahan dari key jsonnya, ada juga yang salah dari penamaan variable. Hmmmm … yang menarik itu adalah yang kesalahan dari penamaan variable, kenapa bisa?? Nanti deh gue jelasin setelah udah masuk ke tutorialnya πŸ˜€ .

Hal pertama yang harus lu lakukan sebelum menerapkan CRUD request di android, pahami dulu bro struktur json bagaimana, lalu buatlah model yang sesuai dengan struktur json tersebut. Untuk struktur json yang akan kita terapkan di tutorial ini, seperti ini gambarannya:

Buat lu yang masih kebingungan untuk struktur projeknya, nih gue kasih bro untuk project structurenya.

Ohh iya bro, untuk menerapkan ini CRUD request ini, gue hanya menggunakan 2 method yaitu GET dan POST. Bisa aja sih menerapkan PUT dan DELETE juga, tapi gue gak mau ribet lah untuk hal itu πŸ˜€ hahaha … ya walaupun menghemat endpoint yang ada, tapi tetep aje gue maunye pake 2 method itu aja πŸ˜€ hahahaa …

Okey, sekarang saatnya untuk masuk ke langkah-langkah tutorial CRUD Android, cekiiddoottt …

Tentu langkah yang paling awal pasti projectnya sudah di buatya bro πŸ˜€ kalo gak dibuat nanti mau naruh dimana kode-kodenya hhaha πŸ˜€ . Setelah itu, lu harus menambahkan beberapa dependencies di file build.gradle, seperti ini bro tambahannya:

implementation 'com.android.support:recyclerview-v7:27.1.1'
// Network
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.8.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1'

Untuk lebih lengkapnya seperti ini

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "id.renaldirey.restapi"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    buildTypes.each {
        it.buildConfigField 'String', 'BASE_URL', BASE_URL
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    // Network
    implementation 'com.squareup.retrofit2:retrofit:2.1.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
    implementation 'com.squareup.okhttp3:okhttp:3.8.1'
    implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.8.1'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1'

    implementation 'android.arch.work:work-runtime:1.0.0-alpha04'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Ohh iya, karena gue memakai gradle version di atas 3.0, jadinya gue gunain implementation. Untuk lu yang memakai gradle version di bawah itu, bisa langsung ganti aja kok kata “implementation” jadi “compile“.

Setelah itu, lari ke file gradle.properties untuk konfigurasi base urlnya. Cukup cantumkan seperti ini aja

BASE_URL = "http://192.x.xx.xxx/"

Perlu di inget bro untuk bagian ini, gue saranin untuk mengubah isi dari “BASE_URL” karena itu hanyalah sebuah contoh, kalo lu sudah memiliki server sendiri dan juga sudah berdomain, berikan urlnya aja atau berikan ip addressnya. Nah gimana untuk local server?? Bisa kok bro, untuk contoh project ini gue gunain local server kok yang hanya menggunakan apachenya dari xampp. Gimana untuk mengakses local server?? Pastikan koneksi laptop/komputer lu dengan android itu satu jaringan internet (kalo projectnya di running di hape kalian masing-masing, perlu diperhatikan hal ini). Untuk yang memakai emulator sudah tidak perlu khawatir πŸ˜€ hahaha … Selanjutnya adalah cek ip address komputer/laptop kalian dengan cara ke cmd (buat pengguna windows aja nih πŸ˜€ ) lalu ketik ipconfig, jika sudah di enter pasti keluar teks (“Ethernet adapter” blablabla πŸ˜€ ), nah yang di ambil adalah yang bagian IPv4 bro πŸ˜€ itulah ip address kalian πŸ˜€ . Kalo semuanya udah oke sinkronisasi projectnya lalu lanjut ke tahap berikutnya πŸ˜€

Masih bingung buat nambahin di file gradle.properties?? Nih gue kasih gambar deh mumpung kodenya gak begitu banyak hahahaha …

Untuk pengkodean selanjutnya adalah buat file yang bernama “ServiceGenerator.java” seperti yang udah gue perlihatkan sebelumnya untuk struktur projectnya, lalu kode lengkapnya di file ServiceGenerator.java seperti ini:

public class ServiceGenerator {
    private static OkHttpClient.Builder builder() {
        OkHttpClient.Builder okhttpBuilder = new OkHttpClient().newBuilder();
        okhttpBuilder.connectTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.writeTimeout(60, TimeUnit.SECONDS);
        okhttpBuilder.readTimeout(60, TimeUnit.SECONDS);

        return okhttpBuilder;
    }

    private static HttpLoggingInterceptor interceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        return interceptor;
    }
    public static <S> S createBaseService(Context context, Class<S> serviceClass) {
        OkHttpClient.Builder okhttpBuilder = builder();

        if (BuildConfig.DEBUG) {
            okhttpBuilder.addInterceptor(interceptor());
        }

        okhttpBuilder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request newReq = request.newBuilder()
                        .header("Accept", "application/json")
                        .build();
                return chain.proceed(newReq);
            }
        });

        OkHttpClient client = okhttpBuilder.build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Endpoint.API_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        return retrofit.create(serviceClass);
    }
}

Di lanjut ke file Endpoint.java isi seperti ini:

public class Endpoint {
    public static final String API_URL = BuildConfig.BASE_URL;

    public static final String API_CREATE = "/crudandroid/index.php/data/add";
    public static final String API_READ = "/crudandroid/index.php/data/";
    public static final String API_UPDATE = "/crudandroid/index.php/data/edit/";
    public static final String API_DELETE = "/crudandroid/index.php/data/delete/";
    public static final String API_UPLOAD = "/crudandroid/index.php/data/uploadimage/";
}

Pada Endpoint.java, disana hanyalah sebuah endpoint api yang kita request, misal untuk request menambahkan data seperti ini “/crudandroid/index.php/data/add”

Setelah Endpoint dan ServiceGenerator sudah selesai, lanjut ke pembuatan base responsenya. Base response ini hanyalah sebuah skema json yang tidak ada perubahannya, lain lagi jika di bagian key “data” yang merupakan sebuah object. Untuk isi kode yang ada di file BaseResponse.java seperti ini:

public class BaseResponse<T> {
    @SerializedName("error")
    private boolean error;
    @SerializedName("message")
    private String message;
    @SerializedName("data")
    private T data;

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

Di awal gue udah jelasin terkait kesalahan mereka ketika memakai retrofit2, salah satunya hal ini bro di pencocokkan key jsonnya. Nah, sebagai informasi aja nih bro, untuk bagian mencocokkan key json itu menurut gue ada 2, tetapi lebih aman menggunakan @SerializedName(“key”). Kalo lu menggunakan itu, untuk penamaan variablepun bebas, mau di samakan dengan key json dan nama variablenya ya gak ada masalah bro, hahaha. Lain hal kalo lu gak menggunakan @SerializedName(“key”), berarti untuk mencocokkan key jsonnya melalui nama variablenya. Jadi, silahkan di pilih bro hahahaha … Kalo gue sih biar aman ya menggunakan @SerializedName(“key”). Setau gue sih kegunaan @SerializedName(“key”) itu ya untuk mencocokkan key json yang ada πŸ˜€ jadi mohon maaf kalo ada yang berpendapat penjelasan gue ini ngawur dsb πŸ˜€ maklumlah gue orangnye gak teoritis hahaha …

Okey bro, lanjut ke pemodelannya nih, untuk isi kode yang ada pada file Data.java di direktori model seperti ini:

public class Data implements Parcelable {
    @SerializedName("id_data")
    String id;
    @SerializedName("name")
    String name;

    protected Data(Parcel in) {
        id = in.readString();
        name = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Data> CREATOR = new Creator<Data>() {
        @Override
        public Data createFromParcel(Parcel in) {
            return new Data(in);
        }

        @Override
        public Data[] newArray(int size) {
            return new Data[size];
        }
    };

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Baru dah bro masuk ke DataService.java, hahahaha … Karena disana perlu untuk menentukan model skema jsonnya πŸ˜€ kalo misalkan dibuat belakangan untuk modelnya yowiss tak apa bro πŸ˜€ ya seenak lu aja yang penting jalan lah hahahaha … Untuk isi kode yang ada pada DataService.java seperti ini:

public interface DataService {
    @FormUrlEncoded
    @POST(Endpoint.API_CREATE)
    Call<BaseResponse> apiCreate(@Field("name") String nama);

    @GET(Endpoint.API_READ)
    Call<BaseResponse<List<Data>>> apiRead();

    @FormUrlEncoded
    @POST(Endpoint.API_UPDATE+"{id}")
    Call<BaseResponse> apiUpdate(
            @Path("id") String id,
            @Field("name") String name
    );

    @POST(Endpoint.API_DELETE+"{id}")
    Call<BaseResponse> apiDelete(@Path("id") String id);
}

Setelah semua itu selesai, barulah lu jalanin requestnya dimana aja, mau di activity kek, atau fragment kek ya terserah lau dah πŸ˜€ hahahaha … Ohh iya sebelum masuk ke yang lainnya, buatlah listenernya untuk berinteraksi dengan tombol-tombol yang dibutuhkan, misal untuk project ini ada 2 tombol di dalam satu adapter, ada tombol untuk edit dan juga untuk menghapus data. Maka buatlah 2 listener. Untuk penamaan listenernya, bisa lu lihat lagi ke atas untuk struktur projeknya bro. Di masing-masing listenernya hanya berisi begini bro, ini untuk detail kode pada file OnUpdateClickListener.java:

public interface OnUpdateClickListener {
    void onUpdateClick(int position);
}

Dan ini untuk detail kode pada file OnDeleteClickListener.java:

public interface OnDeleteClickListener {
    void onDeleteClick(int position);
}

Okey bro, langsung ke penggunaan retrofit2nya nih πŸ˜€ hahahaa … Untuk layout, di projek gue ini cukup 4 layout aja, disana ada layout untuk activity data, activity utama dan activity untuk mengedit data. Dan satu layout lagi untuk list adapternya. Untuk mengawalinya, kita mulai dari MainActivity.java dulu ya bro πŸ˜€ hahhaha … Ohh iye maaf nih layout designnya gak menarik, kan hanya untuk belajar aja jadinya gak perlu mendesign app yang wow untuk latihan, hahaha πŸ˜€ … Untuk detail kode yang ada pada file MainActivity.java seperti ini:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private DataService service;

    private EditText etName;
    private Button btnSubmit;
    private Button btnShow;

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

        service = ServiceGenerator.createBaseService(this, DataService.class);
    }

    private void initListener() {
        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = etName.getText().toString();

                if(isEmpty(name))
                    etName.setError("Must not be empty");
                else
                    addData(name);
            }
        });

        btnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DataActivity.newInstance(MainActivity.this);
            }
        });
    }

    private void addData(String name) {
        Call<BaseResponse> call = service.apiCreate(name);

        call.enqueue(new Callback<BaseResponse>() {
            @Override
            public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
                if(response.code() == 200) {
                    Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_SHORT).show();
                    etName.setText("");
                }
            }

            @Override
            public void onFailure(Call<BaseResponse> call, Throwable t) {
                Log.e(TAG + ".error", t.toString());
            }
        });
    }

    private void initViews() {
        etName = (EditText) findViewById(R.id.et_name);
        btnShow = (Button) findViewById(R.id.btn_show);
        btnSubmit = (Button) findViewById(R.id.btn_submit);
    }
}

Di lanjut lagi ke DataActivity.java, sebelum mengimplementasikan di DataActivity.java, ada baiknya untuk buat adapternya terlebih dulu bro. Nah untuk isi kode yang ada pada file DataAdapter.java seperti ini:

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    Context context;
    List<Data> data;

    OnDeleteClickListener onDeleteClickListener;
    OnUpdateClickListener onUpdateClickListener;

    public DataAdapter(Context context) {
        this.context = context;
        data = new ArrayList<>();
    }

    public void add(Data item) {
        data.add(item);
        notifyItemInserted(data.size() - 1);
    }

    public void addAll(List<Data> items) {
        for (Data item : items) {
            add(item);
        }
    }

    public void setOnDeleteClickListener(OnDeleteClickListener onDeleteClickListener) {
        this.onDeleteClickListener = onDeleteClickListener;
    }

    public void setOnUpdateClickListener(OnUpdateClickListener onUpdateClickListener) {
        this.onUpdateClickListener = onUpdateClickListener;
    }

    public Data getData(int position) {
        return data.get(position);
    }

    public void remove(int position) {
        if (position >= 0 && position < data.size()) {
            data.remove(position);
            notifyItemRemoved(position);
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bind(data.get(position));
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView tvNomer;
        TextView tvName;
        Button btnEdit;
        Button btnRemove;

        public ViewHolder(ViewGroup parent) {
            super(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_data, parent, false));
            initViews();

            btnEdit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onUpdateClickListener.onUpdateClick(getAdapterPosition());
                }
            });

            btnRemove.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onDeleteClickListener.onDeleteClick(getAdapterPosition());
                }
            });
        }

        public void bind(Data item) {
            int nomer = getAdapterPosition() + 1;
            tvNomer.setText(String.valueOf(nomer));
            tvName.setText(item.getName());
        }

        public void initViews() {
            tvNomer = (TextView) itemView.findViewById(R.id.tv_nomer);
            tvName = (TextView) itemView.findViewById(R.id.tv_name);
            btnEdit = (Button) itemView.findViewById(R.id.btn_edit);
            btnRemove = (Button) itemView.findViewById(R.id.btn_delete);
        }
    }
}

Dan untuk DataActivity.java seperti ini bro:

public class DataActivity extends AppCompatActivity implements OnDeleteClickListener, OnUpdateClickListener {

    private static final String TAG = DataActivity.class.getSimpleName();

    private RecyclerView rvData;
    private DataAdapter adapter;
    private DataService service;

    public static void newInstance(Context context) {
        Intent intent = new Intent(context, DataActivity.class);
        context.startActivity(intent);
    }

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

        // Initialization adapter
        adapter = new DataAdapter(this);
        rvData.setLayoutManager(new LinearLayoutManager(this));
        service = ServiceGenerator.createBaseService(this, DataService.class);

        rvData.setAdapter(adapter);
        loadData();
    }

    private void loadData() {
        Call<BaseResponse<List<Data>>> call = service.apiRead();
        call.enqueue(new Callback<BaseResponse<List<Data>>>() {
            @Override
            public void onResponse(Call<BaseResponse<List<Data>>> call, Response<BaseResponse<List<Data>>> response) {
                if(response.code() == 200) {
                    adapter.addAll(response.body().getData());
                    initListener();
                }
            }

            @Override
            public void onFailure(Call<BaseResponse<List<Data>>> call, Throwable t) {
                Log.e(TAG+".error", t.toString());
            }
        });
    }

    private void initListener() {
        adapter.setOnDeleteClickListener(this);
        adapter.setOnUpdateClickListener(this);
    }

    private void initViews() {
        rvData = (RecyclerView) findViewById(R.id.rv_data);
    }

    private void doDelete(final int position, String id) {
        Call<BaseResponse> call = service.apiDelete(id);
        call.enqueue(new Callback<BaseResponse>() {
            @Override
            public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
                if(response.code() == 200)
                    adapter.remove(position);
            }

            @Override
            public void onFailure(Call<BaseResponse> call, Throwable t) {
                Log.e(TAG+".errorDelete", t.toString());
            }
        });
    }

    @Override
    public void onDeleteClick(final int position) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Apakah Anda Yakin Ingin Menghapusnya?");
        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                doDelete(position, adapter.getData(position).getId());
            }
        });
        builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show();
    }

    @Override
    public void onUpdateClick(int position) {
        Data data = adapter.getData(position);
        UpdateActivity.newInstance(this, data);
    }
}

Nih yang terakhir bro πŸ˜€ untuk isi kode yang ada pada file UpdateActivity.java seperti ini:

public class UpdateActivity extends AppCompatActivity {

    private static final String TAG = UpdateActivity.class.getSimpleName();

    private EditText etName;
    private Button btnSubmit;
    private DataService service;
    private Data data;

    public static void newInstance(Context context, Data data) {
        Bundle bundle = new Bundle();
        bundle.putParcelable(TAG+".data", data);
        Intent intent = new Intent(context, UpdateActivity.class);
        intent.putExtras(bundle);

        context.startActivity(intent);
    }

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


        if(getIntent() != null) {
            data = getIntent().getParcelableExtra(TAG+".data");
        }

        initViews();

        service = ServiceGenerator.createBaseService(this, DataService.class);

        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = etName.getText().toString();
                Log.e("name", name);

                if(isEmpty(name))
                    etName.setError("Must not be empty");
                else
                    updateData(name);
            }
        });
    }

    private void updateData(String name) {
        Call<BaseResponse> call = service.apiUpdate(data.getId(), name);

        call.enqueue(new Callback<BaseResponse>() {
            @Override
            public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
                if(response.code() == 200) {
                    Toast.makeText(UpdateActivity.this, "Success", Toast.LENGTH_SHORT).show();
                    etName.setText("");
                }
            }

            @Override
            public void onFailure(Call<BaseResponse> call, Throwable t) {
                Log.e(TAG + ".error", t.toString());
            }
        });
    }

    private void initViews() {
        etName = (EditText) findViewById(R.id.et_name);
        btnSubmit = (Button) findViewById(R.id.btn_submit);

        etName.setText(data.getName());
    }
}

Gimana bro πŸ˜€ mudah kan?? Gue yakin sih gak mudah-mudah amat, karena banyaknya file yang dibutuhkan, seperti halnya ServiceGenerator.java, Endpoint.java dan DataService.java. Ohh iya sama pemodelannya Data.java πŸ˜€ . Kalo menurut gue pribadi sih lebih enakkan menggunakan retrofit2 sih daripada library network yang lain πŸ˜€ Ehh iya yak gue kan cuma nyobain di retrofit2 doang untuk library network, yang lainnya belum gue coba hahaha πŸ˜€ … Apa mungkin karena gue terlalu nyaman menggunakan retrofit2 jadinya gak pengen coba library network yang lain πŸ˜€ bisa jadi sih bro hahhahaha …

Ohh iya bro, ada satu hal yang belum gue bahas, yaitu detail kode yang ada pada file-file layoutnya πŸ˜€ wuaahhh gue sampe lupa hahaha … Di ringkas ajalah yak πŸ˜€
Ini bro untuk detail kode pada file activity_data.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_data"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

</android.support.constraint.ConstraintLayout>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <EditText
        android:id="@+id/et_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Input your name"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/et_name"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:text="Submit"/>

    <Button
        android:id="@+id/btn_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginRight="20dp"
        android:layout_marginLeft="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="10dp"
        android:text="view data"/>

</android.support.constraint.ConstraintLayout>

activity_update.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".UpdateActivity">

    <EditText
        android:id="@+id/et_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Input your name"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/btn_submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/et_name"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:text="Submit"/>

</android.support.constraint.ConstraintLayout>

dan list_data.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tv_nomer"
        android:layout_width="50dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:gravity="center"
        android:textSize="15sp"
        android:text="1"/>
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingLeft="10dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/ll_action"
        app:layout_constraintLeft_toRightOf="@+id/tv_nomer"
        android:textSize="15sp"
        android:gravity="center|left"
        android:text="RenaldiRey.id"/>

    <LinearLayout
        android:id="@+id/ll_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintRight_toRightOf="parent">
        <Button
            android:id="@+id/btn_edit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="edit" />

        <Button
            android:id="@+id/btn_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="hapus" />
    </LinearLayout>
</android.support.constraint.ConstraintLayout>

Oke bro, sekian dari tutorial perdana gue terkait tentang CRUD REST API Using Retrofit2 with Java Language πŸ˜€ . Sekali-kali lah bro gue mengeluarkan kata-kata inggris gue hahahaha πŸ˜€ walaupun masih bermodalkan translate, hahaha … πŸ˜€ Jujur amat yak gue hahhaahahaha … bodo amatan lah yak πŸ˜€ Syukur-syukur kalo ada orang luar negeri yang berkunjung kemari dan hanya butuh kode, kalo butuh penjelasannya juga, hmmmmmmm … gimana yaahhh?? hahahaha …

Kalo ada yang di rasa bingung dan sebagainya, coba di tanyakkan langsung aje bro melalui kolom komentar yang gue open ini πŸ˜€ fast response kok hahahaha … Ehh tapi gak tau juga deh, hahahahaha …

Segitu dulu aja dah bro, ohh iya untuk engine backend Rest API nanti aja yak, bahasnya di lain thread aja πŸ˜€ hahahaha … Semoga bermanfaat bro buat lu yang lagi belajar penggunaan web service di client android. Mohon maaf yak kalo penjelasan gue ada yg agak belibet dsb πŸ˜€ hahahaha … Untuk lu yang ingin view github gue atau pengen clone project terkait latihan CRUD ini, bisa kunjungi diΒ https://github.com/renaldi2108/CRUDAndroidRetrofit2

Dan terima kasih juga sudah mampir ke blogΒ RenaldiΒ yang seadanya begini bro πŸ˜€ πŸ˜€ .

Sekian dan terima kasih bro.
Wassalamualaikum War’rahmatulahi Wabarakatu.