12/08/2018, 13:31

Retrofit Android Tutorial to Get JSON from Server

Nếu bạn chưa biết Retrofit là gì thì bạn nên biết rằng Retrofit là một Library của Android đã được phát triển bới square. Nó cũng đơn giản hoá các hoạt động kết nối Network trong Android. Trong bài viết ngắn này tôi sẽ cùng các bạn tìm hiểu về cách sử dụng của library này. Trong bài viết này ...

Nếu bạn chưa biết Retrofit là gì thì bạn nên biết rằng Retrofit là một Library của Android đã được phát triển bới square. Nó cũng đơn giản hoá các hoạt động kết nối Network trong Android. Trong bài viết ngắn này tôi sẽ cùng các bạn tìm hiểu về cách sử dụng của library này.

Trong bài viết này chúng ta sẽ tạo một ứng dụng đơn giản để giải thích về htpp để tạo ra request sử dụng Retrofit library.

Vậy chúng ta hãy băt đầu. Để minh hoạ cho việc sử dụng Retrofit. Tôi giả sử rằng chúng ta có một web API để trả về một chuỗi json đơn giản.

http://simplifiedcoding.16mb.com/RetrofitExample/books.json

Chúng ta sẽ tạo request tới Url trên và nhận về một chuỗi json đơn giản như bên dưới.

[
 {
 "bookId":"1",
 "name":"Harry Potter and The Prisoner of Azkaban",
 "price":"INR 700.00",
 "inStock":"52"
 },

 {
 "bookId":"2",
 "name":"Hamlet",
 "price":"INR 1700.00",
 "inStock":"47"
 },

 {
 "bookId":"3",
 "name":"Willy Wonka and His Chocolate Factory",
 "price":"INR 500.00",
 "inStock":"48"
 },

 {
 "bookId":"4",
 "name":"Before I Fall",
 "price":"INR 750.00",
 "inStock":"49"
 }

]

Như bạn nhìn thấy nó là một JSON Array có một vài detail của book. Chúng ta sẽ lấy chuỗi dữ liệu này vào trong ứng dụng mẫu của chúng ta sử dung Retrofit. Vậy chúng tao tạo một ứng dụng mới

Retrofit Android

Adding dependencies and Creating Layout

Tạo một Android Studio Project mới và thêm đoạn code dưới vào dependencies của bạn (trong build.gradle)

compile 'com.squareup.retrofit:retrofit:1.9.0'

Bởi vì trong ứng dụng của chúng ta sẽ làm những hoạt động Network nên chúng ta cần quyền truy cập Internet. Vậy add nó tới manifest.

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

Bây giờ tới activity_main.xml và tạo một ListView. Trong tutorial này tôi sẽ hiển thị tên của những quyển sách trong ListView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_awidth="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
 <ListView
        android:id="@+id/listViewBooks"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content">
    </ListView>
 </RelativeLayout>

Tạo một file layout cho hiển thị mỗi item trong ListView.

 <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_awidth="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="20sp" >
 </TextView>

Creating Retrofit Model

Một điều tuyệt vời trong việc sử dụng Retrofit là bạn không cần phải parse Json bởi vì Retrofit sẽ làm điều đó cho bạn. Bạn chỉ cần tạo một model. Chúng ta sẽ tạo một class java với tên là Book.java và thêm đoạn code như bên dưới.

public class Book {

    //Variables that are in our json
    private int bookId;
    private String name;
    private String price;
    private int inStock;

    //Getters and setters
    public int getBookId() {
        return bookId;
    }

    public void setBookId(int bookId) {
        this.bookId = bookId;
    }

    public String getName() {
        return name;
    }

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

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public int getInStock() {
        return inStock;
    }

    public void setInStock(int inStock) {
        this.inStock = inStock;
    }
}

Bạn không cần phải làm quá nhiều thứ trong các class model. Bạn chỉ cần định nghĩa các biến trong json. Trong mỗi Json Object có 4 thuộc tính (id, name, price and stock) vậy tôi tạo ra 4 biến ở đây và sau đó định nghĩa các phương thức setters và getters cho mỗi biến. Bây giờ chúng ta sẽ tạo Retrofit Api.

Creating Interface to Send HTTP Request using Retrofit

Chúng ta sẽ tạo một interface để xử lý request của chúng ta. Chúng ta sẽ tạo BookAPI.java

import java.util.List;

import retrofit.Callback;
import retrofit.http.GET;

/**
 * Created by Belal on 11/3/2015.
 */
public interface BooksAPI {

    /*Retrofit get annotation with our URL
       And our method that will return us the list ob Book
    */
    @GET("/RetrofitExample/books.json")
    public void getBooks(Callback<List<Book>> response);
}

  • Ở trên chúng ta đã định nghĩa một GET Request. Nếu bạn còn đang nhầm lẫn vê URL trong request trên thì thực tế là trong Retrofit chúng ta không cần phải điền toàn bộ URL. Ở đây chúng ta chỉ bỏ phần root của URL là http://www.simplifiedcoding.16mb.com/. Chúng ta sẽ định nghĩa root của URL trong MainActivity.java
  • Chúng ta cũng định nghĩa một phương thức có một đối số Callback. Chúng tao có một callback của một List dữ liệu chúng ta đã định nghĩa trong ví dụ này là Book. Phương thức này sẽ trả về cho chúng ta một List Book.
  • Trong Activity đầu tiên chúng ta sẽ hiển thị duy nhât tên của những quển sách trong một list. Khi người dùng Click trên mỗi Item của List chúng ta sẽ hiển thị chi tiết trong Activity tiếp theo.
  • Tôi sẽ tạo một ShowBookDetails.java và activity_show_book_details.xml trong .xml file. Tôi sẽ tạo 4 TextView để hiển thị các trường book id, name, price and stock.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_awidth="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="net.simplifiedcoding.androidretrofitexample.ShowBookDetails">

    <TextView
        android:id="@+id/textViewBookId"
        android:textSize="24dp"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewBookName"
        android:textSize="24dp"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewBookPrice"
        android:textSize="24dp"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textViewBookInStock"
        android:textSize="24dp"
        android:layout_awidth="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Bây giờ trong MainActivity.java

import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.List;

import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;

//Class having OnItemClickListener to handle the clicks on list
public class MainActivity extends AppCompatActivity implements ListView.OnItemClickListener {

    //Root URL of our web service
    public static final String ROOT_URL = "http://simplifiedcoding.16mb.com/";

    //Strings to bind with intent will be used to send data to other activity
    public static final String KEY_BOOK_ID = "key_book_id";
    public static final String KEY_BOOK_NAME = "key_book_name";
    public static final String KEY_BOOK_PRICE = "key_book_price";
    public static final String KEY_BOOK_STOCK = "key_book_stock";

    //List view to show data
    private ListView listView;

    //List of type books this list will store type Book which is our data model
    private List<Book> books;

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

        //Initializing the listview
        listView = (ListView) findViewById(R.id.listViewBooks);

        //Calling the method that will fetch data
        getBooks();

        //Setting onItemClickListener to listview
        listView.setOnItemClickListener(this);
    }

    private void getBooks(){
        //While the app fetched data we are displaying a progress dialog
        final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);

        //Creating a rest adapter
        RestAdapter adapter = new RestAdapter.Builder()
                .setEndpoint(ROOT_URL)
                .build();

        //Creating an object of our api interface
        BooksAPI api = adapter.create(BooksAPI.class);

        //Defining the method
        api.getBooks(new Callback<List<Book>>() {
            @Override
            public void success(List<Book> list, Response response) {
                //Dismissing the loading progressbar
                loading.dismiss();

                //Storing the data in our list
                books = list;

                //Calling a method to show the list
                showList();
            }

            @Override
            public void failure(RetrofitError error) {
                //you can handle the errors here
            }
        });
    }

    //Our method to show list
    private void showList(){
        //String array to store all the book names
        String[] items = new String[books.size()];

        //Traversing through the whole list to get all the names
        for(int i=0; i<books.size(); i++){
            //Storing names to string array
            items[i] = books.get(i).getName();
        }

        //Creating an array adapter for list view
        ArrayAdapter adapter = new ArrayAdapter<String>(this,R.layout.simple_list,items);

        //Setting adapter to listview
        listView.setAdapter(adapter);
    }

    //This method will execute on listitem click
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //Creating an intent
        Intent intent = new Intent(this, ShowBookDetails.class);

        //Getting the requested book from the list
        Book book = books.get(position);

        //Adding book details to intent
        intent.putExtra(KEY_BOOK_ID,book.getBookId());
        intent.putExtra(KEY_BOOK_NAME,book.getName());
        intent.putExtra(KEY_BOOK_PRICE,book.getPrice());
        intent.putExtra(KEY_BOOK_STOCK,book.getInStock());

        //Starting another activity to show book details
        startActivity(intent);
    }
}

Bây giờ chúng ta cần code cho Activity thứ 2 ShowBookDetails.java để hiện thi chi tiết.

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class ShowBookDetails extends AppCompatActivity {

    //Defining views
    private TextView textViewBookId;
    private TextView textViewBookName;
    private TextView textViewBookPrice;
    private TextView textViewBookInStock;

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

        //Initializing Views
        textViewBookId = (TextView) findViewById(R.id.textViewBookId);
        textViewBookName = (TextView) findViewById(R.id.textViewBookName);
        textViewBookPrice = (TextView) findViewById(R.id.textViewBookPrice);
        textViewBookInStock = (TextView) findViewById(R.id.textViewBookInStock);

        //Getting intent
        Intent intent = getIntent();

        //Displaying values by fetching from intent
        textViewBookId.setText(String.valueOf(intent.getIntExtra(MainActivity.KEY_BOOK_ID, 0)));
        textViewBookName.setText(intent.getStringExtra(MainActivity.KEY_BOOK_NAME));
        textViewBookPrice.setText(intent.getStringExtra(MainActivity.KEY_BOOK_PRICE));
        textViewBookInStock.setText(String.valueOf(intent.getIntExtra(MainActivity.KEY_BOOK_STOCK,0)));
    }
}

Trên tôi đã trình bày với các bạn một ví dụ rất đơn giản về cách sử dụng Retrofit.Ngoài ra các bạn có thể tham khảo link sau để hiểu chi tiết hơn. https://futurestud.io/blog/android-basic-authentication-with-retrofit

0