Связь android с web приложения посредством REST архитектуры. Часть 3 Реализация REST в android

4.933 (3)

Ну вот, когда мы ознакомились с некоторым понятиями, мы можем приступать к написанию небольшое приложения для демонстрации работы данной архитектуры. Наше приложения будет делать два запроса. Для получения списка пользователей и для получения пользователя по номеру id.  


 GET /v1/users/ 
 GET /v1/users/{id}

Для Java есть библиотека Retrofit, которая облегчает создания android restfull приложений и с которой мы будем работать, разрабатывая приложения.
Для того что бы подключить библиотеку допишем строки в Gradle что бы мы смогли собрать наш проект и спокойно работать с библиотекой.    
Открываем файл build.gradleи дописываем необходимое:


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:cardview-v7:+'
    compile 'com.squareup.retrofit:retrofit:1.9.0'
    compile 'com.squareup.okhttp:okhttp:2.4.0'
}    

Отлично, теперь нам необходимо создать интерфейс для работы с нашими пользователями. Для этого создаем интерфейс IrestUserApi.

public interface IRestUserApi {
    @GET("/v1/users/")
    void getUserList(retrofit.Callback<List<User>> cb);
    @GET("/v1/users/{id}")
    void getUserById(@Path("id") int userId,retrofit.Callback<User> cb);
}

С помощью аннотаций мы описываем запрос, который будет осуществлять наш метод при обращении на сервер.
И модель пользователя

public class User {
    private int id;
    private String status;
    private int age;
    private String name;
    private String login;
    private  String info;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getLogin() {
        return login;
    }
    public void setLogin(String login) {
        this.login = login;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

После того открываем наш класс MainActivity добавляем там необходимый функционал для работы:

// Адрес нашего сервера, который обрабатывает наши запросы 
private static String URL_API = "http://192.168.0.10/";
//Интерфейс и адаптер для работы с сервером
private  IRestUserApi userApi = null;
private RestAdapter restAdapter = null;
в методе onCreate инициализируем наши переменные
restAdapter = new RestAdapter.Builder().setEndpoint(URL_API).build();
userApi = restAdapter.create(IRestUserApi.class);

Теперь нам необходимо создать методы с помощью которых мы будем получать данные с сервера. Для наглядности работы мы будем использовать небольшие всплывающие сообщения. Для этого мы будем использовать такой компонент как Snackbar

void loadUserFromRestById(final int userId) {
    if (userApi == null) {
        Snackbar.make(mainLayout, "Cant load user", Snackbar.LENGTH_SHORT).show();
        return;
    }
    userApi.getUserById(userId, new Callback<User>() {
        @Override
        public void success(User user, Response response) {
            viewUser(user);
            Snackbar.make(mainLayout, "Load user with id: " + userId, Snackbar.LENGTH_SHORT).show();
        }
        @Override
        public void failure(RetrofitError error) {
            Log.d(LOG_TAG,error.toString());
            Snackbar.make(mainLayout, "Load user by id: "+userId+" error: "+error.toString(), Snackbar.LENGTH_LONG).show();
        }
    });
}

В данном методе используется интерфейс, который мы описали выше. В методе  userApi.getUserById() создается анонимный класс в котором переопределяем 2 метода. Метод success() вызывается при успешном выполнения запроса, а метод failure() при неудачном.
После того как мы успешно выполнили запрос мы получили объект с нашим пользователем, обратите внимание что в примере для понимания работы были опущены различные проверки в дальше мы опишем более подробно. Сейчас же мы учитываем что пользователь которого мы будем получать есть на сервере.      
Второй метод получает весть список пользователей который есть в системе


 void loadUserFromRest() {
    if (userApi == null) {
        Snackbar.make(mainLayout, "Cant load user", Snackbar.LENGTH_SHORT).show();
        return;
    }
    userApi.getUserList(new Callback<List<User>>() {
        @Override
        public void success(List<User> users, Response response) {
            Snackbar.make(mainLayout, "Load all users success.", Snackbar.LENGTH_SHORT).show();
            viewUserList(users);
        }
        @Override
        public void failure(RetrofitError error) {
            Snackbar.make(mainLayout, "Load all users error: "+error.toString(), Snackbar.LENGTH_LONG).show();
        }
    });
}

В методах  viewUser(user);  и viewUserList(users); мы отображаем на наших компонентах и давайте их реализуем


void viewUserList(List<User> list) {
    userListLayout.removeAllViews();
    for (User item : list) {
        View userItem = LayoutInflater.from(getApplicationContext()).inflate(R.layout.users_list_item, null);
        TextView userName = (TextView) userItem.findViewById(R.id.user_text_name);
        userName.setText(item.getName());
        TextView userId = (TextView) userItem.findViewById(R.id.user_text_id);
        userId.setText(Integer.toString(item.getId()));
        if (item.getStatus().equalsIgnoreCase("admin")) {
            ImageView image = (ImageView)userItem.findViewById(R.id.user_icon);
            image.setImageResource(R.mipmap.ic_account_key_grey600_36dp);
        }
        userListLayout.addView(userItem);
    }
}
void viewUser(User user) {
    userListLayout.removeAllViews();
    View userItem = LayoutInflater.from(getApplicationContext()).inflate(R.layout.user_item, null);
    TextView userName = (TextView) userItem.findViewById(R.id.user_text_name);
    userName.setText(user.getName());
    TextView userId = (TextView) userItem.findViewById(R.id.user_text_id);
    userId.setText(Integer.toString(user.getId()));
    if (user.getStatus().equalsIgnoreCase("admin")) {
        ImageView image = (ImageView)userItem.findViewById(R.id.user_icon);
        image.setImageResource(R.mipmap.ic_account_key_grey600_36dp);
    }
    TextView userAge = (TextView) userItem.findViewById(R.id.user_text_age);
    userAge.setText(Integer.toString(user.getAge()));
    TextView userLogin = (TextView) userItem.findViewById(R.id.user_text_login);
    userLogin.setText(user.getLogin());
    TextView userInfo = (TextView) userItem.findViewById(R.id.user_text_info);
    userInfo.setText(user.getInfo());
    userListLayout.addView(userItem);
}

Теперь нам необходимо вернутся к нажим кнопочкам и заполнить обработчики событий, которые на данный момент у нас пустые.   
Ниже показан полностью класс MainActivity в котором можно увидеть что на кнопке получения списка вызывается метод loadUserFromRest(); а на второй loadUserFromRest();


package ua.com.sidstudio.demorestapi;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class MainActivity extends AppCompatActivity {
    private static String LOG_TAG = "USER_REST_APP";
    private static String URL_API = "http://192.168.0.10/";
    private Button loadUsers;
    private Button loadUsersById;
    private TextView userCaption;
    private EditText editTextUserId;
    private CoordinatorLayout mainLayout;
    private LinearLayout userListLayout;
    private FloatingActionButton fab;
    private List<User> listUserFromRest = new ArrayList<User>();
    private  IRestUserApi userApi = null;
    private RestAdapter restAdapter = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainLayout = (CoordinatorLayout)findViewById(R.id.main_coordinator_layout);
        loadUsers = (Button)findViewById(R.id.button_load_list);
        loadUsersById = (Button)findViewById(R.id.button_load_user);
        userCaption = (TextView)findViewById(R.id.title_caption);
        editTextUserId = (EditText)findViewById(R.id.edittext_user_id);
        userListLayout = (LinearLayout)findViewById(R.id.users_view_layout);
        fab = (FloatingActionButton)findViewById(R.id.fab);
        restAdapter = new RestAdapter.Builder().setEndpoint(URL_API).build();
        userApi = restAdapter.create(IRestUserApi.class);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadUserFromRest();
            }
        });
        loadUsersById.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String inputId = editTextUserId.getText().toString();
                int id;
                try {
                    id = Integer.parseInt(inputId);
                    loadUserFromRestById(id);
                } catch (NumberFormatException e) {
                    Snackbar.make(mainLayout, "Error parsing numbers. Please enter the correct number!", Snackbar.LENGTH_LONG).show();
                }
            }
        });
        loadUsers.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadUserFromRest();
            }
        });
    }
    void viewUserList(List<User> list) {
        userListLayout.removeAllViews();
        for (User item : list) {
            View userItem = LayoutInflater.from(getApplicationContext()).inflate(R.layout.users_list_item, null);
            TextView userName = (TextView) userItem.findViewById(R.id.user_text_name);
            userName.setText(item.getName());
            TextView userId = (TextView) userItem.findViewById(R.id.user_text_id);
            userId.setText(Integer.toString(item.getId()));
            if (item.getStatus().equalsIgnoreCase("admin")) {
                ImageView image = (ImageView)userItem.findViewById(R.id.user_icon);
                image.setImageResource(R.mipmap.ic_account_key_grey600_36dp);
            }
            userListLayout.addView(userItem);
        }
    }
    void viewUser(User user) {
        userListLayout.removeAllViews();
        View userItem = LayoutInflater.from(getApplicationContext()).inflate(R.layout.user_item, null);
        TextView userName = (TextView) userItem.findViewById(R.id.user_text_name);
        userName.setText(user.getName());
        TextView userId = (TextView) userItem.findViewById(R.id.user_text_id);
        userId.setText(Integer.toString(user.getId()));
        if (user.getStatus().equalsIgnoreCase("admin")) {
            ImageView image = (ImageView)userItem.findViewById(R.id.user_icon);
            image.setImageResource(R.mipmap.ic_account_key_grey600_36dp);
        }
        TextView userAge = (TextView) userItem.findViewById(R.id.user_text_age);
        userAge.setText(Integer.toString(user.getAge()));
        TextView userLogin = (TextView) userItem.findViewById(R.id.user_text_login);
        userLogin.setText(user.getLogin());
        TextView userInfo = (TextView) userItem.findViewById(R.id.user_text_info);
        userInfo.setText(user.getInfo());
        userListLayout.addView(userItem);
    }
    void loadUserFromRest() {
        if (userApi == null) {
            Snackbar.make(mainLayout, "Cant load user", Snackbar.LENGTH_SHORT).show();
            return;
        }
        userApi.getUserList(new Callback<List<User>>() {
            @Override
            public void success(List<User> users, Response response) {
                Snackbar.make(mainLayout, "Load all users success.", Snackbar.LENGTH_SHORT).show();
                viewUserList(users);
            }
            @Override
            public void failure(RetrofitError error) {
                Snackbar.make(mainLayout, "Load all users error: "+error.toString(), Snackbar.LENGTH_LONG).show();
            }
        });
    }
    void loadUserFromRestById(final int userId) {
        if (userApi == null) {
            Snackbar.make(mainLayout, "Cant load user", Snackbar.LENGTH_SHORT).show();
            return;
        }
        userApi.getUserById(userId, new Callback<User>() {
            @Override
            public void success(User user, Response response) {
                viewUser(user);
                Snackbar.make(mainLayout, "Load user with id: " + userId, Snackbar.LENGTH_SHORT).show();
            }
            @Override
            public void failure(RetrofitError error) {
                Log.d(LOG_TAG,error.toString());
                Snackbar.make(mainLayout, "Load user by id: "+userId+" error: "+error.toString(), Snackbar.LENGTH_LONG).show();
            }
        });
    }
}

Теперь нам необходимо прописать на файл с манифестом и дописать туда разрешения на использования сети в приложении. Открываение файл AndroidManifest.xml и пишем туда 

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

Теперь когда к нас все готово можно запускать наше приложения. В данной статье мы не рассматриваем написание северной части, а для тестирования можно написать всего пару строчек
Для первого запроса 


$json = '{id:7,status:"admin",age:23,name:"Angelina",login:"tmp_d",info:"this a simple admin in system"}';
echo $json;    

для второго 

$json = '[
    {id:1,status:"admin",age:18,name:"Leo",login:"tmp_a",info:"this a main admin in system"},
    {id:2,status:"client",age:12,name:"Mary",login:"tmp_b",info:"our vip user"},
    {id:3,status:"admin",age:16,name:"Adam",login:"tmp_c",info:"this a main admin in system"},
    {id:4,status:"client",age:18,name:"Lee",login:"tmp_d",info:""},
    {id:5,status:"client",age:33,name:"Leonardo",login:"tmp_r",info:"our user"},
    {id:6,status:"admin",age:43,name:"Candy",login:"tmp_z",info:"this a super admin in system"},
    {id:7,status:"admin",age:23,name:"Angelina",login:"tmp_d",info:"this a simple admin in system"}
    ]';
echo $json;

Запускаем наше приложения и смотрим на то что мы написали

Загружаем наш список пользователей

android+rest

И загружаем отдельно пользователя

android+rest

 

Исходный код можете скачать по ссылке:

https://www.dropbox.com/s/spufyaxru9r4xv8/DemoRestApi.zip?dl=0

Комментарий (0)

Войдите с помощью соцсетей:
или
введите свои данные: