Chuyển đến nội dung chính

Các bước cơ bản sử dụng Retrofit để thao tác với API và MVP

 Cài đặt  Retrofit

//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
Cài đặt Gson

implementation 'com.google.code.gson:gson:2.8.9'

Cài thư viện Okhttp
implementation 'com.squareup.okhttp3:okhttp:3.12.0'

Sử dụng Gson ở trong project:
1. Tạo class App
import android.app.Application;
import com.google.gson.Gson;


public class App extends Application {
private static App mSelf;
private Gson mGSon;

public static App self() {
return mSelf;
}

@Override
public void onCreate() {
super.onCreate();
mSelf = this;
mGSon = new Gson();
}

public Gson getGSon() {
return mGSon;
}
}

2. Chỉnh file AndroidManifest:
<?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="vn.gov.vn.quanlyvanbansonganh">

<application
android:name=".app.App"
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/AppTheme"
android:usesCleartextTraffic="true">
<activity android:name=".TestActivity">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->

<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
</activity>
<activity
android:name=".ThongTinNguoiDungActivity"
android:label="@string/user_info"
android:parentActivityName=".WebViewActivity" />
<activity
android:name=".HomeActivity"
android:label="@string/title_activity_home" />
<activity android:name=".SplashScreenActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".WebViewActivity"
android:noHistory="true" />
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar"
tools:ignore="ExtraText" />

<service
android:name=".AppService.OnClearFromRecentService"
android:stopWithTask="false" />


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

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

</manifest>
3. Tạo class SharedPrefs để đọc ghi vào bộ nhớ điện thoại

import android.content.Context;
import android.content.SharedPreferences;

import vn.gov.vn.quanlyvanbansonganh.WebViewActivity;
import vn.gov.vn.quanlyvanbansonganh.app.App;

public class SharedPrefs {

private static final String APP_SHARED = "APP_SHARED";
public static final String TOKEN_KEY = "TOKEN_KEY";
public static final String MA_DON_VI = "MA_DON_VI";
public static final String TEN_DON_VI = "TEN_DON_VI";
public static final String DON_VI = "DON_VI";
private static SharedPrefs mInstance;
private SharedPreferences mSharedPreferences;

private SharedPrefs() {
mSharedPreferences = App.self().getSharedPreferences(APP_SHARED , Context.MODE_PRIVATE);
}

public static SharedPrefs getInstance() {
if (mInstance == null) {
mInstance = new SharedPrefs();
}
return mInstance;
}

@SuppressWarnings("unchecked")
public <T> T get(String key, Class<T> anonymousClass) {
if (anonymousClass == String.class) {
return (T) mSharedPreferences.getString(key, null);
} else if (anonymousClass == Boolean.class) {
return (T) Boolean.valueOf(mSharedPreferences.getBoolean(key, false));
} else if (anonymousClass == Float.class) {
return (T) Float.valueOf(mSharedPreferences.getFloat(key, 0));
} else if (anonymousClass == Integer.class) {
return (T) Integer.valueOf(mSharedPreferences.getInt(key, 0));
} else if (anonymousClass == Long.class) {
return (T) Long.valueOf(mSharedPreferences.getLong(key, 0));
} else {
return (T) App.self().getGSon().fromJson(mSharedPreferences.getString(key, null), anonymousClass);
}
}

public <T> void put(String key, T data) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
if (data instanceof String) {
editor.putString(key, (String) data);
} else if (data instanceof Boolean) {
editor.putBoolean(key, (Boolean) data);
} else if (data instanceof Float) {
editor.putFloat(key, (Float) data);
} else if (data instanceof Integer) {
editor.putInt(key, (Integer) data);
} else if (data instanceof Long) {
editor.putLong(key, (Long) data);
} else {
editor.putString(key, App.self().getGSon().toJson(data));
}
editor.apply();
}

public void clear() {
mSharedPreferences.edit().clear().apply();
}

public void ClearToken(){
mSharedPreferences.edit().remove(SharedPrefs.TOKEN_KEY).apply();
}

public void ClearLastURL(){
mSharedPreferences.edit().remove(WebViewActivity.LAST_URL).apply();
}
}
4. Tạo class Constant chứa các hằng
public class Constant {

public static final String URL_BASE = "domain";

public static final String URL_DANH_SACH_DON_VI = "ds_donvi";

public static final String URL_LOGIN = "dangnhap";

public static final String URL_THONG_TIN_NGUOI_DUNG = "api_get_info/";


// Biến phục vụ đọc và ghi SharedPreferences
public static final String APP_SHARED = "APP_SHARED";
public static final String TOKEN_KEY = "TOKEN_KEY";


}

Cấu hình Retrofit:
1. Tạo class RetrofitClient

import com.google.gson.GsonBuilder;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClient {
private static Retrofit retrofit = null;

public static Retrofit getRetrofit(String baseUrl){
OkHttpClient builder = new OkHttpClient.Builder()
.readTimeout(10000, TimeUnit.MILLISECONDS)
.writeTimeout(10000, TimeUnit.MILLISECONDS)
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true)
.build();

Gson gson = new GsonBuilder().setLenient().create();
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit;
}
}

Tạo interface APIService:

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;

import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.Url;
import vn.gov.vn.quanlyvanbansonganh.config.Constant;
import vn.gov.vn.quanlyvanbansonganh.model.response.DanhSachDonViResult;
import vn.gov.vn.quanlyvanbansonganh.model.response.LoginResult;
import vn.gov.vn.quanlyvanbansonganh.model.response.ThongTinNguoiDungResult;

public interface APIService {

// @GET
// Call<DanhSachDonViResult> GetDanhSachDonVi(@Url String url);

@GET(Constant.URL_DANH_SACH_DON_VI)
Call<DanhSachDonViResult> GetDanhSachDonVi();

@FormUrlEncoded
@POST(Constant.URL_LOGIN)
Call<LoginResult> Login(@Field("donvi") int maDonvi,@Field("username") String username,@Field("password") String password);

@GET(Constant.URL_THONG_TIN_NGUOI_DUNG + "{token}")
Call<ThongTinNguoiDungResult> GetThongTinNguoiDung(@Path("token") String token);
}



Viết chức năng Login:
1. Tạo ModelLoginResult:


import com.google.gson.annotations.SerializedName;

public class LoginResult {

@SerializedName("status")
public Boolean status;

@SerializedName("result")
public String message;

@SerializedName("token")
public String token;

public Boolean getStatus() {
return status;
}

public void setStatus(Boolean status) {
this.status = status;
}

public String getMessage() {
return message;
}

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

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}
}

2. Tạo interface ILoginPresenter

public interface ILoginPresenter {

void Login(int maDonvi,String username,String password);
}


3. Tạo classs LoginPresenterCompl
public class LoginPresenterCompl implements ILoginPresenter {

private String token;
private ILoginView iLoginView;


public LoginPresenterCompl(ILoginView iLoginView) {
this.iLoginView = iLoginView;
}

@Override
public void Login(final int maDonvi, String username, String password) {
iLoginView.onSetProgressBarVisibility();
APIService service = RetrofitClient.getRetrofit(Constant.URL_BASE).create(APIService.class);
Call<LoginResult> callBack = service.Login(maDonvi, username, password);

callBack.enqueue(new Callback<LoginResult>() {
@Override
public void onResponse(Call<LoginResult> call, Response<LoginResult> response) {
if (response.isSuccessful()) {
if (response.body().token != null) {

token = response.body().token;
iLoginView.SaveToken(token);
// iLoginView.SaveDonVi(maDonvi);
iLoginView.signInSuccess();

} else
iLoginView.signInFailure(response.body().message);

}
}

@Override
public void onFailure(Call<LoginResult> call, Throwable t) {
iLoginView.signInFailure("Không kết nối được máy chủ");
}
});
}
}

4.Tạo frament Login:

public class LoginFragment extends Fragment implements ILoginView {

private ILoginPresenter iLoginPresenter;
private EditText edtUserName;
private EditText edtPassword;
private Button btnLogin;
private ProgressBar progressBar;
private LinearLayout layoutLogin;

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private DonVi donVi;

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private String username;
private String password;


public LoginFragment() {
// Required empty public constructor
}

/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param //param1 Parameter 1.
* @param //param2 Parameter 2.
* @return A new instance of fragment LoginFragment.
*/
// TODO: Rename and change types and number of parameters
//public static LoginFragment newInstance(String param1, String param2)
public static LoginFragment newInstance() {
LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle();
// args.putString(ARG_PARAM1, param1);
// args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);

}


}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_login, container, false);
edtUserName = root.findViewById(R.id.edt_username);
edtPassword = root.findViewById(R.id.edt_password);
btnLogin = root.findViewById(R.id.btn_login);
progressBar = root.findViewById(R.id.progressBarLogin);
layoutLogin = root.findViewById(R.id.LinearLogin);
iLoginPresenter = new LoginPresenterCompl(this);

final PageViewModel model = new ViewModelProvider(requireActivity()).get(PageViewModel.class);
model.getDonVi().observe(getViewLifecycleOwner(), new Observer<DonVi>() {
@Override
public void onChanged(DonVi mDonVi) {
if (mDonVi != null)
donVi = mDonVi;
}
});

btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
username = edtUserName.getText().toString();
password = edtPassword.getText().toString();
if (donVi != null)
{
Log.d("MADONVI",String.valueOf(donVi.getDonvi_id()));
iLoginPresenter.Login(10156, username, password);
}
else{
onSetTextToast("Bạn chưa chọn đơn vị");
model.setIndex(0);
}
}
});
return root;
}

@Override
public void onSetProgressBarVisibility() {
progressBar.setVisibility(View.VISIBLE);
}

@Override
public void onSetProgressBarInvisibility() {
progressBar.setVisibility(View.INVISIBLE);
}

@Override
public void signInSuccess() {
onSetProgressBarInvisibility();
layoutLogin.setVisibility(View.INVISIBLE);
SaveDonVi(donVi);
ShowWebView();
//getActivity().finish();
}

@Override
public void signInFailure(String error) {
onSetProgressBarInvisibility();
layoutLogin.setVisibility(View.VISIBLE);
onSetTextToast(error);

}

@Override
public void onResume() {
super.onResume();
layoutLogin.setVisibility(View.VISIBLE);
}

@Override
public void onSetTextToast(String msg) {
Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
}

@Override
public void SaveToken(String token) {
SharedPrefs.getInstance().put(SharedPrefs.TOKEN_KEY,token);

}

@Override
public void SaveDonVi(DonVi donVi) {
SharedPrefs.getInstance().put(SharedPrefs.DON_VI,donVi);
}

@Override
public void ShowWebView() {
Intent intent = new Intent(getActivity(), WebViewActivity.class);
startActivity(intent);
}

}

4.Layout của Fragment Login:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.LoginFragment">

<ProgressBar
android:id="@+id/progressBarLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:indeterminate="true"
android:visibility="invisible" />

<LinearLayout
android:id="@+id/LinearLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="180dp"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">

<EditText
android:id="@+id/edt_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên đăng nhập"
android:selectAllOnFocus="true"
android:singleLine="true" />

<EditText
android:id="@+id/edt_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mật khẩu"
android:inputType="textPassword"
android:singleLine="true" />

<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Đăng Nhập" />

</LinearLayout>

</RelativeLayout>
Lấy danh sách bằng Retrofit

1. Tao interface IHomePresenter

public interface IHomePresenter {

void loadBQC(String token, int filter);

BienQuangCao getBienQuangCao(List<BienQuangCao> bienQuangCaoList, String bqc_id);

void timBienQuangCao(String token, String query);


2. Tạo interface IHomeView
public interface IHomeView {

void onSetProgressBarVisibility();

void onSetProgressBarInvisibility();

void onSetTextToast(String msg);

void addMakerToMap(List<BienQuangCao> bienQuangCaoList);

void setDanhSachBQC(List<BienQuangCao> bienQuangCaoList);

void addOneMarker(BienQuangCao bienQuangCao);

void moveCamera(BienQuangCao bienQuangCao);

void addItemListBienQuangCao(List<BienQuangCao> list, List<BienQuangCao> newListItem);

}
3. Tạo class HomePresenterCompl:
public class HomePresenterCompl implements IHomePresenter {

private static final String TAG = HomePresenterCompl.class.getSimpleName();
private IHomeView iHomeView;

public HomePresenterCompl(IHomeView iHomeView) {
this.iHomeView = iHomeView;
}

@Override
public void loadBQC(String token, int filter) {
// Hiện progressbar khi nhấn nút thêm bqc
iHomeView.onSetProgressBarVisibility();

APIService service = RetrofitClient.getRetrofit(Constant.URL_BASE).create(APIService.class);
Call<HomeResult> callBack = service.DanhSachBienQuangCao(token, filter);
callBack.enqueue(new Callback<HomeResult>() {
@Override
public void onResponse(Call<HomeResult> call, Response<HomeResult> response) {
if(response.isSuccessful()){
assert response.body() != null;
if(response.body().getError())
iHomeView.onSetTextToast(response.body().getMessage());
else if(response.body().getBienQuangCaoList().size() > 0)
{
iHomeView.onSetProgressBarInvisibility();
// Log.d(TAG,String.valueOf(response.body().getBienQuangCaoList()));
iHomeView.addMakerToMap(response.body().getBienQuangCaoList());
iHomeView.setDanhSachBQC(response.body().getBienQuangCaoList());

}
else
{
iHomeView.onSetProgressBarInvisibility();
iHomeView.onSetTextToast(response.body().getMessage());
}
}
}

@Override
public void onFailure(Call<HomeResult> call, Throwable t) {
iHomeView.onSetTextToast("Không kết nối được máy chủ");


}
});


}

@Override
public BienQuangCao getBienQuangCao(List<BienQuangCao> bienQuangCaoList, String bqc_id) {
BienQuangCao bienQuangCao = Iterables.tryFind(bienQuangCaoList,
new Predicate<BienQuangCao>() {
@Override
public boolean apply(@NullableDecl BienQuangCao input) {
return bqc_id.contains(input.getBqc_id());
}
}).orNull();
return bienQuangCao;
}

@Override
public void timBienQuangCao(String token, String query) {
// Hiện progressbar khi nhấn nút thêm bqc
iHomeView.onSetProgressBarVisibility();

APIService service = RetrofitClient.getRetrofit(Constant.URL_BASE).create(APIService.class);
Call<HomeResult> callBack = service.TimBQC(token, query);
callBack.enqueue(new Callback<HomeResult>() {
@Override
public void onResponse(Call<HomeResult> call, Response<HomeResult> response) {
if(response.isSuccessful()){
assert response.body() != null;
if(response.body().getError())
iHomeView.onSetTextToast(response.body().getMessage());
else if(response.body().getBienQuangCaoList().size() > 0)
{
List<BienQuangCao> bienQuangCaoList = response.body().getBienQuangCaoList();
iHomeView.onSetProgressBarInvisibility();
iHomeView.addMakerToMap(bienQuangCaoList);
iHomeView.setDanhSachBQC(response.body().getBienQuangCaoList());

iHomeView.onSetTextToast("Tìm thấy " + bienQuangCaoList.size() + " biển quảng cáo");
}
else
{
iHomeView.onSetTextToast(response.body().getMessage());
iHomeView.onSetProgressBarInvisibility();
}
}
}

@Override
public void onFailure(Call<HomeResult> call, Throwable t) {
iHomeView.onSetTextToast("Không kết nối được máy chủ");

}
});

}

public void addMakerToMap(GoogleMap map,List<BienQuangCao> bienQuangCaoList) {

map.clear();
MarkerOptions makerOptions = new MarkerOptions();
for (BienQuangCao bienQuangCao : bienQuangCaoList)
{
double lat = 0;
double lng = 0;
if(!bienQuangCao.getBqc_latitude().equals(".") && !bienQuangCao.getBqc_longtidue().equals(".")) {
lat = Double.parseDouble(bienQuangCao.getBqc_latitude());
lng = Double.parseDouble(bienQuangCao.getBqc_longtidue());
// Log.d("LAT",lat +"");
// lng = nf.parse(bienQuangCao.getBqc_longtidue()).doubleValue();
makerOptions.position(new LatLng(lat, lng));
// makerOptions.position(mDefaultLocation);

/* if (bienQuangCao.getTrang_thai() == 3 || bienQuangCao.getTrang_thai() == 2)
makerOptions.icon((BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_VIOLET)));
else if (bienQuangCao.getNoi_dung_qc() != null)
makerOptions.icon((BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
else
makerOptions.icon((BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));*/
if (bienQuangCao.getTrang_thai() == 3 || bienQuangCao.getTrang_thai() == 2)
makerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_advertisement_gray));
else if (bienQuangCao.getNoi_dung_qc() != null)
makerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_advertisement_pillar));
else
makerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_advertisement_pillarfree));

Marker m = map.addMarker(makerOptions);
m.setTag(bienQuangCao.getBqc_id());
}

}
}
}
4. Trong class HomeActivity

public class HomeActivity extends AppCompatActivity implements   IHomeView {
iHomePresenter.loadBQC(NhanVienSQLite.getJsonToKen(),Constant.TAT_CA);
Tạo Custom Adapter lấy Danh sách bằng Retrofit:

1. Tạo Model:


public class BienQuangCao implements Serializable {

@SerializedName("BQC_ID")
private String bqc_id;

@SerializedName("BQC_SO_KM")
private String bqc_so_km;

@SerializedName("BQC_HINH_THUC")
private String bqc_hinh_thuc;

@SerializedName("BQC_KICH_THUOC")
private String bqc_kich_thuoc;

@SerializedName("BQC_GOOGLE_X")
private String bqc_latitude;

@SerializedName("BQC_GOOGLE_Y")
private String bqc_longtidue;

@SerializedName("BQC_NGUOI_NHAP_ID")
private String nhanvien_id;

@SerializedName("BQC_LOAI_BIEN_QUANG_CAO")
private int ma_loai_bqc;

@SerializedName("BQC_DAT_CONG_CA_NHAN")
private int ma_loai_so_huu_dat;

@SerializedName("BQC_CHU_SO_HUU")
private int ma_chu_so_huu;

@SerializedName("DV_TEN_DON_VI")
private String chu_so_huu;

@SerializedName("BQC_DIA_CHI")
private String dia_diem;

@Nullable
@SerializedName("HS_NOI_DUNG_QUANG_CAO")
private String noi_dung_qc;

@SerializedName("BQC_TRANG_THAI")
private int trang_thai;

@Nullable
@SerializedName("HS_NGAY_BAT_DAU")
private String tu_ngay;

@Nullable
@SerializedName("HS_NGAY_KET_THUC")
private String toi_ngay;

public BienQuangCao(String bqc_id, String dia_diem) {
this.bqc_id = bqc_id;
this.dia_diem = dia_diem;
}

public String getTu_ngay() {
return tu_ngay;
}

public void setTu_ngay(String tu_ngay) {
this.tu_ngay = tu_ngay;
}

public String getToi_ngay() {
return toi_ngay;
}

public void setToi_ngay(String toi_ngay) {
this.toi_ngay = toi_ngay;
}

public void setNoi_dung_qc(String noi_dung_qc) {
this.noi_dung_qc = noi_dung_qc;
}

public String getNoi_dung_qc() {
return noi_dung_qc;
}

public String getBqc_id() {
return bqc_id;
}

public void setBqc_id(String bqc_id) {
this.bqc_id = bqc_id;
}

public String getBqc_so_km() {
return bqc_so_km;
}

public void setBqc_so_km(String bqc_so_km) {
this.bqc_so_km = bqc_so_km;
}

public String getBqc_hinh_thuc() {
return bqc_hinh_thuc;
}

public void setBqc_hinh_thuc(String bqc_hinh_thuc) {
this.bqc_hinh_thuc = bqc_hinh_thuc;
}

public String getBqc_kich_thuoc() {
return bqc_kich_thuoc;
}

public void setBqc_kich_thuoc(String bqc_kich_thuoc) {
this.bqc_kich_thuoc = bqc_kich_thuoc;
}

public String getBqc_latitude() {
return bqc_latitude;
}

public void setBqc_latitude(String bqc_latitude) {
this.bqc_latitude = bqc_latitude;
}

public String getBqc_longtidue() {
return bqc_longtidue;
}

public void setBqc_longtidue(String bqc_longtidue) {
this.bqc_longtidue = bqc_longtidue;
}

public String getNhanvien_id() {
return nhanvien_id;
}

public void setNhanvien_id(String nhanvien_id) {
this.nhanvien_id = nhanvien_id;
}

public int getMa_loai_bqc() {
return ma_loai_bqc;
}

public void setMa_loai_bqc(int ma_loai_bqc) {
this.ma_loai_bqc = ma_loai_bqc;
}

public int getMa_loai_so_huu_dat() {
return ma_loai_so_huu_dat;
}

public void setMa_loai_so_huu_dat(int ma_loai_so_huu_dat) {
this.ma_loai_so_huu_dat = ma_loai_so_huu_dat;
}

public int getMa_chu_so_huu() {
return ma_chu_so_huu;
}

public void setMa_chu_so_huu(int ma_chu_so_huu) {
this.ma_chu_so_huu = ma_chu_so_huu;
}

public String getChu_so_huu() {
return chu_so_huu;
}

public void setChu_so_huu(String chu_so_huu) {
this.chu_so_huu = chu_so_huu;
}

public String getDia_diem() {
return dia_diem;
}

public void setDia_diem(String dia_diem) {
this.dia_diem = dia_diem;
}

public int getTrang_thai() {
return trang_thai;
}

public void setTrang_thai(int trang_thai) {
this.trang_thai = trang_thai;
}

/* @Override
public String toString() {
return "BienQuangCao{" +
"bqc_id='" + bqc_id + '\'' +
", bqc_so_km='" + bqc_so_km + '\'' +
", bqc_hinh_thuc='" + bqc_hinh_thuc + '\'' +
", bqc_kich_thuoc='" + bqc_kich_thuoc + '\'' +
", bqc_latitude='" + bqc_latitude + '\'' +
", bqc_longtidue='" + bqc_longtidue + '\'' +
", nhanvien_id='" + nhanvien_id + '\'' +
", ma_loai_bqc=" + ma_loai_bqc +
", ma_loai_so_huu_dat=" + ma_loai_so_huu_dat +
", ma_chu_so_huu=" + ma_chu_so_huu +
", chu_so_huu='" + chu_so_huu + '\'' +
", dia_diem='" + dia_diem + '\'' +
", noi_dung_qc='" + noi_dung_qc + '\'' +
'}';
}*/

@NonNull
@Override
public String toString() {
String result;

if(bqc_id.equals("Chọn biển quảng cáo"))
result = bqc_id;
else
result = bqc_id + " " + "(" + dia_diem + ")";
return result;
}
}
2. Tạo custom_view danh_sach_bqc_card_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="3dp"
card_view:cardCornerRadius="@dimen/radiusCardView"
card_view:cardBackgroundColor="@color/colorBackgroundCardView"
card_view:cardElevation="8dp">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/tv_ma_bqc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/tvColorTieuDe"
android:textSize="@dimen/tvTieuDeSize"
android:textStyle="bold"
android:paddingLeft="10dp"
android:paddingRight="10dp"/>


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/linearPaddingTop"
android:paddingBottom="@dimen/linearPaddingBottom"
>


<ImageView
android:layout_width="@dimen/iconWidth"
android:layout_height="@dimen/iconHeight"
card_view:srcCompat="@drawable/ic_chu_so_huu_image" />

<TextView
android:id="@+id/tv_chu_so_huu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/tvTextColorCardView"
android:textSize="@dimen/tvTextSizeCardView"
android:layout_marginLeft="@dimen/tvMarginLeftCardView"
/>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/linearPaddingTop"
android:paddingBottom="@dimen/linearPaddingBottom"
>


<ImageView
android:layout_width="@dimen/iconWidth"
android:layout_height="@dimen/iconHeight"
card_view:srcCompat="@drawable/ic_bien_quang_cao_image" />

<TextView
android:id="@+id/tv_bqc_quang_cao_hien_tai"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/tvTextColorCardView"
android:textSize="@dimen/tvTextSizeCardView"
android:layout_marginLeft="@dimen/tvMarginLeftCardView"

/>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/linearPaddingTop"
android:paddingBottom="@dimen/linearPaddingBottom"
>


<ImageView
android:layout_width="@dimen/iconWidth"
android:layout_height="@dimen/iconHeight"
card_view:srcCompat="@drawable/ic_tu_ngay_icon" />

<TextView
android:id="@+id/tv_bqc_tu_ngay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/tvTextColorCardView"
android:textSize="@dimen/tvTextSizeCardView"
android:layout_marginLeft="@dimen/tvMarginLeftCardView"

/>
</LinearLayout>


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/linearPaddingTop"
android:paddingBottom="@dimen/linearPaddingBottom"
>


<ImageView
android:layout_width="@dimen/iconWidth"
android:layout_height="@dimen/iconHeight"
card_view:srcCompat="@drawable/ic_toi_ngay_icon" />

<TextView
android:id="@+id/tv_bqc_den_ngay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/tvTextColorCardView"
android:textSize="@dimen/tvTextSizeCardView"
android:layout_marginLeft="@dimen/tvMarginLeftCardView"


/>
</LinearLayout>


</LinearLayout>


</LinearLayout>
</androidx.cardview.widget.CardView>

3. Tạo custom adapter DanhSachBienQuangCaoAdapter:
package cantho.quanlyquangcao.custom_adapter;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.google.common.collect.Iterables;


import java.util.List;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import cantho.quanlyquangcao.R;
import cantho.quanlyquangcao.config.Constant;
import cantho.quanlyquangcao.model.BienQuangCao;
import cantho.quanlyquangcao.utils.Converter;


public class DanhSachBienQuangCaoAdapter extends RecyclerView.Adapter<DanhSachBienQuangCaoAdapter.BienQuangCaoViewHolder> {

private List<BienQuangCao> dsBienQuangCao;
private LayoutInflater mLayoutInflater;
private Context context;

public DanhSachBienQuangCaoAdapter(List<BienQuangCao> dsLuanChuyen, Context context) {
this.dsBienQuangCao = dsLuanChuyen;
mLayoutInflater = LayoutInflater.from(context);
this.context = context;
}

@NonNull
@Override
public BienQuangCaoViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

//inflate view danh_sach_luan_chuyen_card_view.xml
View itemView = mLayoutInflater.inflate(R.layout.danh_sach_bqc_card_view,viewGroup,false);
return new BienQuangCaoViewHolder(itemView);
}

@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull BienQuangCaoViewHolder holder, int i) {

BienQuangCao bienQuangCao = dsBienQuangCao.get(i);

//bind data to viewholder
holder.tvMaBQC.setText("Mã biển quảng cáo: " + bienQuangCao.getBqc_id());
holder.tvChuSoHuu.setText(bienQuangCao.getChu_so_huu() + "");
if(bienQuangCao.getNoi_dung_qc() != null)
holder.tvQuangCaoHienTai.setText(bienQuangCao.getNoi_dung_qc());

if(bienQuangCao.getTu_ngay() != null)
holder.tvTuNgay.setText(Converter.PrintDate(bienQuangCao.getTu_ngay()));

if(bienQuangCao.getToi_ngay() != null)
holder.tvDenNgay.setText(Converter.PrintDate(bienQuangCao.getToi_ngay()));


}

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


public class BienQuangCaoViewHolder extends RecyclerView.ViewHolder {
private TextView tvMaBQC;
private TextView tvChuSoHuu;
private TextView tvQuangCaoHienTai;
private TextView tvTuNgay;
private TextView tvDenNgay;



public BienQuangCaoViewHolder(View itemView) {
super(itemView);
tvMaBQC = itemView.findViewById(R.id.tv_ma_bqc);
tvChuSoHuu = itemView.findViewById(R.id.tv_chu_so_huu);
tvQuangCaoHienTai = itemView.findViewById(R.id.tv_bqc_quang_cao_hien_tai);
tvTuNgay = itemView.findViewById(R.id.tv_bqc_tu_ngay);
tvDenNgay = itemView.findViewById(R.id.tv_bqc_den_ngay);

itemView.setOnClickListener(v -> {

BienQuangCao bienQuangCao = Iterables.tryFind(dsBienQuangCao,
input -> tvMaBQC.getText().toString().contains(input.getBqc_id())).orNull();

Intent intent = ((Activity) context).getIntent();
intent.putExtra(Constant.BIEN_QUANG_CAO,bienQuangCao);

((Activity) context).setResult(Constant.RESULT_BIEN_QUANG_CAO, intent);
((Activity) context).finish();
});
}
}
}

4. Tạo DanhSachBienQuangCaoActivity:
package cantho.quanlyquangcao;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cantho.quanlyquangcao.config.Constant;
import cantho.quanlyquangcao.custom_adapter.DanhSachBienQuangCaoAdapter;
import cantho.quanlyquangcao.model.BienQuangCao;

import android.annotation.SuppressLint;
import android.os.Bundle;

import java.util.List;

public class DanhSachBienQuangCaoActivity extends AppCompatActivity {

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

private RecyclerView recyclerDSBQC;

private List<BienQuangCao> listBienQuangCao;


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

listBienQuangCao = (List<BienQuangCao>) getIntent().getSerializableExtra(Constant.DS_BIEN_QUANG_CAO);
AddControls();

}

private void AddControls(){
recyclerDSBQC = findViewById(R.id.recyDanhSachBQC);

DanhSachBienQuangCaoAdapter danhSachBienQuangCaoAdapter = new DanhSachBienQuangCaoAdapter(listBienQuangCao,this);
recyclerDSBQC.setAdapter(danhSachBienQuangCaoAdapter);

@SuppressLint("WrongConstant") LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerDSBQC.setLayoutManager(linearLayoutManager);

}


}
Layout activity_danh_sach_bien_quang_cao:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".DanhSachBienQuangCaoActivity">

<LinearLayout

android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">


<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyDanhSachBQC"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<!-- <Button
android:id="@+id/btnViPham"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Vi Phạm" />-->

</LinearLayout>

<!-- <ProgressBar
android:id="@+id/progressBarChiTietBQC"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true" />-->
</RelativeLayout>
* Chú ý hàm gửi danh sách biển quản cáo cho  DanhSachBienQuangCaoActivity nhận:


if(listBienQuangCao != null) {
Intent intentDanhSachBQC = new Intent(HomeActivity.this, DanhSachBienQuangCaoActivity.class);
intentDanhSachBQC.putExtra(Constant.DS_BIEN_QUANG_CAO, (Serializable) listBienQuangCao);
startActivityForResult(intentDanhSachBQC, Constant.REQUEST_BIEN_QUANG_CAO);
sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
else
onSetTextToast("Không có biển quảng cáo nào trong danh sách");
break;

Một số ví dụ sử dụng Retrofit:

//http://domain.com/v2/api/api_get_info/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6InZhbnRodSIsImRvbnZpIjoiMyIsImNvbXBhbnlJZCI6IjEwMTU2IiwicGFzc3dvcmQiOiIxMjMiLCJ0aW1lIjoiMjAyMS0wNi0xOCAwOTozNTowMCIsIkFQSV9USU1FIjoxNjIzOTgzNzAwfQ.UyiCOHh5JTqVef4FNg6r6UB9jM9JX01YuJtvrT-8mOY
@GET(Constant.URL_USER_INFO + "{token}")
suspend fun userInfo(@Path("token") token:String): Response<UserInfoResponse>

//http://domain.com/qlvb_mobile/api/register_token_device?authorization=TokenNguoiDung&token_device=TokenThietBi
@GET(Constant.URL_INSERT_TOKEN)
suspend fun sendDeviceToken(
@Query("authorization") token: String?,
@Query("token_device") deviceToken: String?
): Response<AddDeviceTokenRespone>
//http://domain.com/v2/api/logout_token_device?token_device=eS6M5ftJRdS71I1MYNVLsP:APA91bEkNCjgaqDjsEY_k8wHVKFXlPQGau670OL2aMeNbVHKbJVXyaxONxE-REFA8380mktrXPW2KqxSbYYlz9mGSF3Tv_ZIsgbjLEeHT9eybWpWsou5t3oj_oF999LrlHb7G6Tt6uiZ
@GET(Constant.URL_REMOVE_DEVICE_TOKEN)
suspend fun deleteDeviceToken(
@Query("token_device") tokenDevice: String?
): Response<DeleteDeviceTokenResponse>

Nhận xét

Bài đăng phổ biến từ blog này

Kích thước icon cho app Android và công cụ tạo icon của Google

Để hiển thị chuẩn theo các size màn hình thì chúng ta sẽ theo các kích thước sau: 36 × 36 (ldpi) – Low 48 × 48 (mdpi) – Medium 72 × 72 (hdpi) – High 96 × 96 (x-hdpi) – x-high 144 × 144 (xx-hdpi) 192 × 192 (xxx-hdpi) 512 × 512 (Google Play store) -> Kích thước này để làm ảnh demo cho App khi upload lên store. Khi tạo icon launcher cho app nếu tạo bằng các  Launcher icon generator  cửa Google thì khi cài vào điện thoại nó sẽ bé hơn so với các app khác vì google tự động cho thêm padding vào icon. Tránh điều này thì nên tự thiết kế bằng Photoshop sau đó dùng  cái này  để tạo thì sẽ to và đẹp hơn, nó tạo nhanh và đủ các kích thước chuẩn như bên trên kia. Nếu bạn muốn bo góc thì cũng làm bo góc ở trong photoshop trước sau đó mới dùng công cụ bên trên. Kiến thức liên quan đến đơn vị đo trong Android: pixel có thể hiểu là số điểm ảnh có trong 1 dot có hình vuông vì là ảnh bitmap mà. Ảnh đen trắng binary image thì 1 dot = 1 px = 1 bit (chỉ có trạng thá...

Cấu trúc cơ bản layout trong Flutter