本文是根據(jù)網(wǎng)絡(luò)視頻所摘抄的筆記:https://www.sunofbeach.net/course
準(zhǔn)備工作
后臺程序:https://github.com/TrillGates/SOBAndroidMiniWeb,請自行克隆運行
-
本文需要的一些第三方插件和庫:
// gradle: Android{ ... compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } } implementation 'com.github.bumptech.glide:glide:4.3.1' //圖片異步加載 annotationProcessor 'com.github.bumptech.glide:compiler:4.3.1' implementation 'com.google.code.gson:gson:2.8.6' //解析json數(shù)據(jù)的,設(shè)置中記得下載插件 implementation 'com.android.support:recyclerview-v7:28.0.0' // implementation 'com.jakewharton:butterknife:8.8.1' //注解工具睁枕,設(shè)置中記得下載插件 // annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' implementation("com.squareup.okhttp3:okhttp:4.3.1") implementation "com.squareup.retrofit2:retrofit:2.7.1" //OKhttp的二次封裝框架 implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
-
需要下載的兩個軟件
PostMan:獲取后臺接口給出的數(shù)據(jù) Fiddler4:網(wǎng)頁爬蟲工具,獲取網(wǎng)頁的一些數(shù)據(jù)等
權(quán)限配置:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
android:usesCleartextTraffic="true"http://網(wǎng)絡(luò)明文配置实愚,還有一種xml配置(百度)
private static final int PEMISSION_CODE = 1;
//讀寫權(quán)限的動態(tài)配置
int result = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if (result!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},PEMISSION_CODE);
}
//網(wǎng)絡(luò)的動態(tài)權(quán)限
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.INTERNET},1);
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="postRequest"
android:text="postRequest"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getWithParams"
android:text="getWithParams"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="postWithParams"
android:text="postWithParams"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="postFiles"
android:text="postFiles"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="downloadFile"
android:text="downloadFile"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="picLoadActivity"
android:text="picLoadActivity"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="mainActivity"
android:text="mainActivity"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="okhttpActivity"
android:text="okhttpActivity"
android:textAllCaps="false" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="retrofitActivity"
android:text="retrofitActivity"
android:textAllCaps="false" />
</LinearLayout>
代碼:
@RequiresApi(api = Build.VERSION_CODES.M)
public class PostTestActivity extends AppCompatActivity {
private static final int PEMISSION_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request_test);
int result = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if (result!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},PEMISSION_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private static final String TAG = "PostTestActivity";
private static final String BASE_URL = "http://10.0.2.2:9102";
public void getWithParams(View view){
Map<String,String> params = new HashMap<>();
params.put("keyword","這是我的關(guān)鍵字KeyWord");
params.put("page","12");
params.put("order","0");
startRequest(params,"GET","/get/param");
}
public void postWithParams(View view){
Map<String,String> params = new HashMap<>();
params.put("string","這是我提交的post字符串");
startRequest(params,"POST","/post/string");
}
public void postFiles(View view){
new Thread(new Runnable() {
@Override
public void run() {
OutputStream outputStream = null;
/*BufferedInputStream bfi = null;
InputStream inputStream = null;*/
try {
File fileOne = new File("/storage/emulated/0/Download/u=582768544,3207336121&fm=173&app=49&f=JPEG.jpeg");
File fileTwo = new File("/storage/emulated/0/Download/u=2072603009,1469009397&fm=173&app=49&f=JPEG.jpeg");
File fileThree = new File("/storage/emulated/0/Download/u=713976396,3151553386&fm=173&app=49&f=JPEG.jpeg");
String BOUNDARY = "--------------------------550224162623810134726503";
// String BOUNDARY = "----------------------------954555323792164398227139";
// String BOUNDARY = "----------------------------954555323792164398227139--";
String fileKey = "files";
// String fileName = fileOne.getName();
String fileTye = "image/jpeg";
URL url = new URL(BASE_URL+"/files/upload");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.setRequestProperty("User-Agent","Android/"+ Build.VERSION.SDK_INT);
urlConnection.setRequestProperty("Accept","*/*");
urlConnection.setRequestProperty("Cache-Control","no-cache");
urlConnection.setRequestProperty("Content-Type", "multipart/from-data; boundary=" + BOUNDARY);
urlConnection.setRequestProperty("Connection", "keep-alive");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
//連接
urlConnection.connect();
outputStream = urlConnection.getOutputStream();
//準(zhǔn)備數(shù)據(jù)
uploadFile(fileOne, BOUNDARY, fileKey, fileOne.getName(), fileTye, outputStream,false);
uploadFile(fileTwo, BOUNDARY, fileKey, fileTwo.getName(), fileTye, outputStream,false);
uploadFile(fileThree, BOUNDARY, fileKey, fileThree.getName(), fileTye, outputStream,true);
outputStream.flush();
//獲取返回結(jié)果
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "responseCode ===========>" + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
String s = bf.readLine();
Log.d(TAG, "result =========>"+s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
/*if (bfi != null) {
try {
bfi.close();
} catch (IOException e) {
e.printStackTrace();
}
}*/
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
private void uploadFile(
File file,
String BOUNDARY,
String fileKey,
String fileName,
String fileTye,
OutputStream outputStream,
boolean isLast) throws IOException {
StringBuilder headerInfo = new StringBuilder();
headerInfo.append("--");
headerInfo.append(BOUNDARY);
headerInfo.append("\r\n");//兼容Windows和Linux
headerInfo.append("Content-Disposition: form-data; name="+fileKey+"; filename="+fileName);
headerInfo.append("\r\n");
headerInfo.append("Content-Type: "+ fileTye);
headerInfo.append("\r\n");
headerInfo.append("\r\n");
byte[] headerInfoBytes = headerInfo.toString().getBytes("UTF-8");
outputStream.write(headerInfoBytes);
//文件內(nèi)容
FileInputStream fos = new FileInputStream(file);
BufferedInputStream bfi = new BufferedInputStream(fos);
byte[] buffer = new byte[1024];
int len;
while((len = bfi.read(buffer,0,buffer.length)) != -1){
outputStream.write(buffer,0,len);
}
//寫尾部信息
StringBuilder footerInfo = new StringBuilder();
footerInfo.append("\r\n");
footerInfo.append("--");
footerInfo.append(BOUNDARY);
if(isLast){
footerInfo.append("--");
footerInfo.append("\r\n");
}
footerInfo.append("\r\n");
outputStream.write(footerInfo.toString().getBytes("UTF-8"));
}
}).start();
}
private void startRequest(final Map<String, String> params, final String method, final String api) {
new Thread(new Runnable() {
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
//組裝參數(shù)
StringBuilder sb = new StringBuilder();
if (params != null && params.size() > 0) {
sb.append("?");
Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> next = iterator.next();
sb.append(next.getKey());
sb.append("=");
sb.append(next.getValue());
if (iterator.hasNext()) {
sb.append("&");
}
}
Log.d(TAG, "sb -------- result:" + sb.toString());
}
URL url;
String params = sb.toString();
if (params != null && params.length() > 0) {
url = new URL(BASE_URL + api + params);
}else{
url = new URL(BASE_URL + api);
}
Log.d(TAG, "url ==========> "+ url.toString());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(method);
urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
urlConnection.setRequestProperty("Accept","*/*");
urlConnection.connect();
int responseCode = urlConnection.getResponseCode();
if (responseCode== HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String json = bufferedReader.readLine();
Log.d(TAG, "result =========> " + json);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
public void postRequest(View v) {
new Thread(new Runnable() {
@Override
public void run() {
OutputStream outputStream = null;
InputStream inputStream = null;
try {
URL url = new URL(BASE_URL+"/post/comment");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
urlConnection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9");
urlConnection.setRequestProperty("Accept", "application/json, text/plain, */*");
CommentItem commentItem = new CommentItem("454654", "實打?qū)嵢龅?);
Gson gson = new Gson();
String jsonStr = gson.toJson(commentItem);
byte[] bytes = jsonStr.getBytes("UTF-8");
Log.d(TAG, "run: ------->" + bytes.length);
urlConnection.setRequestProperty("Content-Length", String.valueOf(bytes.length));
//連接
urlConnection.connect();
//把數(shù)據(jù)給到服務(wù)器
outputStream = urlConnection.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
//拿結(jié)果
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
inputStream = urlConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
Log.d(TAG, "result------> " + bufferedReader.readLine());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
public void downloadFile(View v){
new Thread(new Runnable() {
@Override
public void run() {
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
URL url = new URL(BASE_URL + "/download/10");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(10000);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
urlConnection.setRequestProperty("Accept","*/*");
urlConnection.connect();
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "responseCode =========>" + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
/*Map<String, List<String>> headerFields = urlConnection.getHeaderFields();
for (Map.Entry<String, List<String>> stringListEntry : headerFields.entrySet()) {
Log.d(TAG, stringListEntry.getKey() + "============" + stringListEntry.getValue());
}
List<String> strings = headerFields.get("Content-disposition");
for (String string : strings) {
Log.d(TAG, "string =====" + string);
}*/
String headerField = urlConnection.getHeaderField("Content-disposition");
Log.d(TAG, "headerField -----------> " + headerField);
/*int index = headerField.indexOf("filename=");
String fileName = headerField.substring(index + "filename=".length());
Log.d(TAG, "fileName ============ " + fileName);*/
String fileName = headerField.replace("attachment; filename=", "");
Log.d(TAG, "fileName ============ " + fileName);
File picFile = PostTestActivity.this.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
Log.d(TAG, "picFile ========= " + picFile);
if (!picFile.exists()) {
picFile.mkdirs();
}
File file = new File(picFile + File.separator + fileName);
if (!file.exists()) {
file.createNewFile();
}
fileOutputStream = new FileOutputStream(file);
inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
fileOutputStream.write(buffer,0,len);
}
fileOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeIO(inputStream);
IOUtils.closeIO(fileOutputStream);
}
}
}).start();
}
public void picLoadActivity(View view){
Intent intent = new Intent(this,PicLoadActivity.class);
startActivity(intent);
}
public void mainActivity(View view){
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);
}
public void okhttpActivity(View view){
Intent intent = new Intent(this, OkHttpActivity.class);
startActivity(intent);
}
public void retrofitActivity(View view){
Intent intent = new Intent(this, RetrofitActivity.class);
startActivity(intent);
}
}
CommentItem.java:
public class CommentItem {
public CommentItem(String articalId, String commentContent) {
this.articalId = articalId;
this.commentContent = commentContent;
}
private String articalId;
private String commentContent;
public String getArticalId() {
return articalId;
}
public void setArticalId(String articalId) {
this.articalId = articalId;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
}
IOUtils.java:
public class IOUtils {
public static void closeIO(Closeable closeable){
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
PicLoadActivity(壓縮圖片)
布局:一按鈕和一個圖片控件
代碼:
public class PicLoadActivity extends AppCompatActivity {
private static final String TAG = "PicLoadActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pic_load);
}
public void loadPic(View v) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
//拿到圖片的大小
BitmapFactory.decodeResource(getResources(), R.drawable.big_bitmap, options);
ImageView imageView = findViewById(R.id.result_image);
/*int outHeight = options.outHeight;
int outWidth = options.outWidth;
Log.i(TAG, "outHeight:---->" + outHeight);
Log.i(TAG, "outWidth:---->" + outWidth);*/
//拿控件的尺寸
int measuredHeight = imageView.getMeasuredHeight();
int measuredWidth = imageView.getMeasuredWidth();
options.inSampleSize = calculateInSampleSize(options,measuredWidth,measuredHeight)+1;
Log.i(TAG, "measuredHeight:---->" + measuredHeight);
Log.i(TAG, "measuredWidth:---->" + measuredWidth);
// options.inSampleSize = 1;
// 圖片的寬度/控件的寬度
// 圖片的高度/控件的高度
// 去兩者間小值
/*if (outHeight > measuredHeight || outWidth > measuredWidth) {
int subHeight = outHeight / measuredHeight;
int subWidth = outWidth / measuredWidth;
options.inSampleSize = subHeight > subWidth ? subWidth : subHeight;
}*/
options.inJustDecodeBounds = false;
Log.d(TAG, "inSampleSize: ==>" + options.inSampleSize);
//根據(jù)控件的大小嗤放,動態(tài)的計算sample值
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.big_bitmap, options);
imageView.setImageBitmap(bitmap);
// new Thread(new Runnable() {
// @Override
// public void run() {
// try {
// URL url = new URL("http://img2.imgtn.bdimg.com/it/u=2813397494,178486986&fm=26&gp=0.jpg");
// HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// urlConnection.setConnectTimeout(10000);
// urlConnection.setRequestMethod("GET");
// urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.8");
// urlConnection.setRequestProperty("Accept","*/*");
// urlConnection.connect();
// int responseCode = urlConnection.getResponseCode();
// if (responseCode == HttpURLConnection.HTTP_OK) {
// InputStream inputStream = urlConnection.getInputStream();
// //轉(zhuǎn)成bitmap
// final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
// //更新UI镐作,要在主線程里面
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// ImageView imageView = findViewById(R.id.result_image);
// imageView.setImageBitmap(bitmap);
// }
// });
//
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// }
// }).start();
}
public static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) {
//這里其實是獲取到默認(rèn)的高度和寬度暮顺。也就是圖片的實際高度和寬度
final int height = options.outHeight;
final int width = options.outWidth;
//默認(rèn)采樣率為1,也就是不變嘛响驴。
int inSamplesize = 2;
//..核心算法.......
if (width > maxWidth || height > maxHeight) {
if (width > height) {
inSamplesize = Math.round((float) height / (float) maxHeight);
} else {
inSamplesize = Math.round((float) width / (float) maxWidth);
}
final float totalPixels = width * height;
final float maxTotalPixels = maxWidth * maxHeight * 2;
while (totalPixels / (inSamplesize * inSamplesize) > maxTotalPixels) {
inSamplesize++;
}
}
return inSamplesize;
}
}
MainActivity(Gson以及RecyclerView的使用)
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="loadurl"
android:onClick="loadUrl"
android:textAllCaps="false"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
代碼:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public GetResultlistAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.INTERNET},1);
initView();
}
private void initView() {
RecyclerView result = findViewById(R.id.recyclerview);
result.setLayoutManager(new LinearLayoutManager(this));
adapter = new GetResultlistAdapter();
result.setAdapter(adapter);
}
public void loadUrl(View view){
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://api.apiopen.top/videoCategoryDetails?id=14");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(10000);
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.8");
connection.setRequestProperty("Accept","*/*");
connection.connect();
//結(jié)果碼
int code = connection.getResponseCode();
if(code == 200){
Map<String, List<String>> headerFilds = connection.getHeaderFields();
Set<Map.Entry<String, List<String>>> entries = headerFilds.entrySet();
for (Map.Entry<String, List<String>> entry : entries) {
Log.d(TAG,entry.getKey() + "==" +entry.getValue());
}
// Object content = connection.getContent();
// Log.d(TAG,"content -- >" + content);
InputStream inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String json = bufferedReader.readLine();
Log.d(TAG, "line -- >"+json);
Gson gson = new Gson();
GetTextItem getTextItem = gson.fromJson(json,GetTextItem.class);
uodateUI(getTextItem);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void uodateUI(final GetTextItem getTextItem) {
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.setData(getTextItem);
}
});
}
}
GetTextIte
public class GetTextItem {
//................略
//內(nèi)容過長透且,即將接口api數(shù)據(jù)復(fù)制,利用gson插件進(jìn)行轉(zhuǎn)換
}
GetResultlistAdapter
public class GetResultlistAdapter extends RecyclerView.Adapter<GetResultlistAdapter.InnerHolder> {
private List<GetTextItem.ResultBean> mdata = new ArrayList<>();
@NonNull
@Override
public InnerHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
//此布局就一圖片和一文本
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_get_text,viewGroup,false);
return new InnerHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull InnerHolder innerHolder, int i) {
View itemView = innerHolder.itemView;
TextView title = itemView.findViewById(R.id.txt);
ImageView image = itemView.findViewById(R.id.img);
GetTextItem.ResultBean.DataBeanX.ContentBean.DataBean databean = mdata.get(i).getData().getContent().getData();
title.setText(databean.getTitle());
Glide.with(image.getContext()).load(databean.getCover().getDetail()).into(image);
}
@Override
public int getItemCount() {
return mdata.size();
}
public void setData(GetTextItem getTextItem) {
mdata.clear();
mdata.addAll(getTextItem.getResult());
notifyDataSetChanged();
}
public class InnerHolder extends RecyclerView.ViewHolder{
public InnerHolder(@NonNull View itemView) {
super(itemView);
}
}
}