안드로이드 5기 2017년 강의 정리 3 (오준석의 생존코딩)
https://www.youtube.com/watch?v=qCyHkVRZnXo&list=PLxTmPHxRH3VWSF7kMcsIaTglWUJZpWeQ9&index=56
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki
MyFirstAndroidApp5ki-master.zip
19일차, 20일차, 24일차, 28일차 메모장, 데이터베이스, Toolbar SearchView, RecyclerView
21일차 갤러리, Glide
22일차 23일차 스레드, AsyncTask, ProgressDialog
24일차 Socket프로그래밍
25일차 채팅 수정
26일차 카톡 짝퉁
26일차 RecyclerView
19일차, 20일차, 24일차, 28일차 메모장, 데이터베이스, Toolbar SearchView, RecyclerView
# SQLite를 사용하여 데이터 저장 (android developers)
https://developer.android.com/training/data-storage/sqlite#java
# SQL Tutorial (w3schools.com)
https://www.w3schools.com/sql/
# MemoActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/MemoActivity.java
# MemoContract.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/db/MemoContract.java
# MemoDbHelper.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/db/MemoDbHelper.java
# MemoFacade.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/db/MemoFacade.java
schema (구조)
SELECT Orders.OrderID, Customers.CustomerName FROM Orders INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID WHERE Customers.CustomerName LIKE 'a__%'; # Wildcards WHERE City LIKE '[bsp]%'; WHERE City LIKE '[a-c]%'; WHERE City LIKE '[!bsp]%'; WHERE City NOT LIKE '[bsp]%'; IN operator WHERE Country IN ('Germany', 'France', 'UK');
21일차 갤러리
# GalleryFragment.java
# GalleryActivity.java
# activity_gallery.xml
# fragment_gallery.xml
22일차 스레드
# Processes and threads overview
https://developer.android.com/guide/components/processes-and-threads#java
# AsyncTask (android developers)
https://developer.android.com/reference/android/os/AsyncTask
# ThreadActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/ThreadActivity.java
# AsyncTaskActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/AsyncTaskActivity.java
# activity_thread.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_thread.xml
# activity_async_task.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_async_task.xml
# GalleryActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/GalleryActivity.java
# GalleryFragment.java (Glide 사용)
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/fragments/GalleryFragment.java
# fragment_gallery.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/fragment_gallery.xml
# activity_gallery.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_gallery.xml
public class ThreadActivity extends AppCompatActivity {
private static final String TAG = ThreadActivity.class.getSimpleName();
private TextView mTextView;
private int mNumber = 0;
private Handler mHandler = new Handler();
private Handler mHandler2 = new Handler() {
@Override
public void handleMessage(Message msg) {
mTextView.setText(msg.what + "");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread);
mTextView = findViewById(R.id.textView);
// 메인 스레드에서는 UI 갱신이 가능
new Thread(new Runnable() {
@Override
public void run() {
// 복잡한 오래 걸리는 처리
for (int i = 0; i < 10; i++) {
mNumber++;
try {
Thread.sleep(500);
// 1. 스레드에서는 UI 갱신이 안 됨
// 2. 스레드에서 Handler를 생성할 수 없다
// Handler를 사용해서 UI 갱신을 해야 됨
mHandler.post(new Runnable() {
@Override
public void run() {
// 글자 변경
mTextView.setText(mNumber + "");
}
});
// 위에 코드와 같은 코드 1
// mHandler2.sendEmptyMessage(mNumber);
// 위에 코드와 같은 코드 2
// 모든 View는 Handler를 가지고 있다
// mTextView.post(new Runnable() {
// @Override
// public void run() {
// mTextView.setText(mNumber + "");
// }
// });
// 위에 코드와 같은 코드 2
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// mTextView.setText(mNumber + "");
// }
// });
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "run: " + i);
}
}
}).start();
}
}
public class AsyncTaskActivity extends AppCompatActivity {
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task);
mTextView = (TextView) findViewById(R.id.text_view);
// 제약사항
// 1. AsyncTask 클래스는 반드시 UI 스레드에서 로드 해야 된다
// 2. AsyncTask 인스턴스는 반드시 UI 스레드에서 생성해야 된다
// 3. execute() 도 반드시 UI 스레드에서 호출해야 된다
// 4. 모든 콜백들은 직접 호출하면 안된다
// 5. 태스크 인스턴스는 한번만 실행할 수 있다.
MyAsyncTask task = new MyAsyncTask();
task.execute(0);
task.cancel(true);
// // 일반적인 사용법
// // 순차적으로 실행
// new MyAsyncTask().execute(0);
// new MyAsyncTask().execute(0);
// new MyAsyncTask().execute(0);
//
// // 병렬로 수행되는 AsyncTask
// new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);
// new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);
}
public void progressClick(View view) {
// new ProgressTask(this).execute();
DownloadDialogFragment fragment =
DownloadDialogFragment.newInstance("처리 중 입니다");
fragment.show(getSupportFragmentManager(), "download");
}
public void downloadClick(View view) {
new DownloadTask(this).execute();
}
public static class DownloadDialogFragment extends DialogFragment {
public static DownloadDialogFragment newInstance(String message) {
DownloadDialogFragment fragment = new DownloadDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("message", message);
fragment.setArguments(bundle);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String message = getArguments().getString("message");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(message);
return builder.create();
}
}
private class DownloadTask extends AsyncTask<Void, Integer, Void> {
private final Context mContext;
private ProgressDialog mDialog;
public DownloadTask(Context context) {
mContext = context;
}
@Override
protected void onPreExecute() {
// 다이얼로그 보이기
mDialog = new ProgressDialog(mContext);
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setMessage("처리 중 입니다 ...");
mDialog.create();
mDialog.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
for (int i = 0; i <= 100; i++) {
Thread.sleep(100);
// UI 갱신
publishProgress(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
mDialog.setProgress(values[0]);
}
@Override
protected void onPostExecute(Void aVoid) {
// 다이얼로그 숨기기
if (mDialog != null) {
mDialog.dismiss();
}
}
}
private class ProgressTask extends AsyncTask<Void, Void, Void> {
private final Context mContext;
private ProgressDialog mDialog;
public ProgressTask(Context context) {
mContext = context;
}
@Override
protected void onPreExecute() {
// 다이얼로그 보이기
mDialog = new ProgressDialog(mContext);
mDialog.setMessage("처리 중 입니다 ...");
mDialog.create();
mDialog.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// 다이얼로그 숨기기
mDialog.dismiss();
}
}
private class MyAsyncTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected void onPreExecute() {
// 최초 실행 되는 부분
}
@WorkerThread // 의미 전달 위해
@Override
protected Integer doInBackground(Integer... params) {
// 오래 걸리는 처리
int number = params[0];
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
number++;
// UI 갱신
publishProgress(number); // onProgressUpdate로 넘어감
}
return number; // onPostExecute로 넘어감
}
@Override
protected void onProgressUpdate(Integer... values) {
// UI 갱신
mTextView.setText(values[0] + "");
}
@Override
protected void onPostExecute(Integer integer) {
// 오래걸리는 처리가 끝난 후 호출
Log.d("AsyncTask", "onPostExecute: " + integer);
}
@Override
protected void onCancelled() {
super.onCancelled();
// 취소 처리
}
}
}
# activity_thread.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_thread"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:textSize="32dp"
android:text="0" />
</RelativeLayout>
# activity_async_task.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_async_task"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="32dp" />
<Button
android:onClick="progressClick"
android:id="@+id/progress_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="처리중" />
<Button
android:onClick="downloadClick"
android:id="@+id/download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="다운로드중" />
</LinearLayout>
23일차 ProgressDialog
# DialogFragment (android developer)
https://developer.android.com/reference/android/app/DialogFragment
# Android AsyncTasks during a screen rotation, Part I
https://fattybeagle.com/2011/02/14/android-asynctasks-during-a-screen-rotation-part-i/
# ProgressDialog (android developer)
https://developer.android.com/reference/android/app/ProgressDialog
24일차 Socket프로그래밍
# Java 소켓 통신 예제
https://gist.github.com/junsuk5/f0ff2298e17853dc48e89f2dfc7bd985
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 1 대 1 소켓 통신 클라이언트 예제
*/
public class Client {
private Socket mSocket;
private BufferedReader mIn;
private PrintWriter mOut;
public Client(String ip, int port) {
try {
// 서버에 요청 보내기
mSocket = new Socket(ip, port);
System.out.println(ip + " 연결됨");
// 통로 뚫기
mIn = new BufferedReader(
new InputStreamReader(mSocket.getInputStream()));
mOut = new PrintWriter(mSocket.getOutputStream());
// 메세지 전달
mOut.println("응답하라!!");
mOut.flush();
// 응답 출력
System.out.println(mIn.readLine());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
// 소켓 닫기 (연결 끊기)
try {
mSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) {
String ip = "192.168.0.10";
int port = 5555;
new Client(ip, port);
}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 1 대 1 소켓 통신 서버 예제
*/
public class Server {
private ServerSocket mServerSocket;
private Socket mSocket;
private BufferedReader mIn; // 들어오는 통로
private PrintWriter mOut; // 나가는 통로
public Server() {
try {
mServerSocket = new ServerSocket(5555);
System.out.println("서버 시작!!!");
// 스레드가 멈춰 있고
// 연결 요청이 들어오면 연결
mSocket = mServerSocket.accept();
System.out.println("클라이언트와 연결 됨");
mIn = new BufferedReader(
new InputStreamReader(mSocket.getInputStream()));
mOut = new PrintWriter(mSocket.getOutputStream());
// 클라이언트에서 보낸 문자열 출력
System.out.println(mIn.readLine());
// 클라이언트에 문자열 전송
mOut.println("전송 잘 되었음");
mOut.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 소켓 닫기 (연결 끊기)
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
mServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Server server = new Server();
}
}
25일차 채팅 수정
# ArrayList 스레드 세이프
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>());
https://madplay.github.io/post/java-collection-synchronize
26일차 카톡 짝퉁
ListView 에서
divider 와
transcriptMode=”alwaysScroll”
# ChatActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/ChatActivity.java
public class ChatActivity extends AppCompatActivity implements View.OnClickListener, ReceiverThread.OnReceiveListener {
public static final String NAME = "채팅남2";
private ListView mMessageListView;
private EditText mMessageEditText;
private SenderThread mThread1;
private Socket mSocket = null;
private ChatAdapter mAdapter;
private ArrayList<Chat> mChatDataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
mMessageListView = (ListView) findViewById(R.id.list_view);
mMessageEditText = (EditText) findViewById(R.id.message_edit);
findViewById(R.id.send_button).setOnClickListener(this);
mChatDataList = new ArrayList<>();
mAdapter = new ChatAdapter(mChatDataList);
mMessageListView.setAdapter(mAdapter);
new Thread(new Runnable() {
@Override
public void run() {
// 일단은 테스트 용으로 본인의 아이피를 입력해서 진행하겠습니다.
try {
mSocket = new Socket("192.168.0.10", 7777);
// 두번째 파라메터 로는 본인의 닉네임을 적어줍니다.
mThread1 = new SenderThread(mSocket, NAME);
ReceiverThread thread2 = new ReceiverThread(mSocket);
thread2.setOnReceiveListener(ChatActivity.this);
mThread1.start();
thread2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void onClick(View v) {
mThread1.sendMessage(mMessageEditText.getText().toString());
mMessageEditText.setText("");
}
@Override
@WorkerThread
public void onReceive(final String message) {
String[] split = message.split(">");
// ~~가 입장하셨습니다 처리 무시
if (split.length < 2) {
return;
}
String nickname = split[0];
String msg = split[1];
final Chat chat = new Chat();
if (NAME.equals(nickname)) {
// 나
chat.isMe = true;
} else {
// 남
chat.isMe = false;
}
chat.nickname = nickname;
chat.message = msg;
// UI 스레드로 실행
runOnUiThread(new Runnable() {
@Override
public void run() {
// 메세지 갱신
mChatDataList.add(chat);
mAdapter.notifyDataSetChanged();
}
});
}
@Override
protected void onDestroy() {
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}
public static class Chat {
public String message;
public String nickname;
public boolean isMe;
}
private static class ChatAdapter extends BaseAdapter {
private final List<Chat> mData;
public ChatAdapter(List<Chat> list) {
mData = list;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_chat, parent, false);
viewHolder.layoutMe = (LinearLayout) convertView.findViewById(R.id.layout_me);
viewHolder.layoutYou = (LinearLayout) convertView.findViewById(R.id.layout_you);
viewHolder.nickname = (TextView) convertView.findViewById(R.id.nickname_text);
viewHolder.bubbleYou = (TextView) convertView.findViewById(R.id.bubble_you_text);
viewHolder.bubbleMe = (TextView) convertView.findViewById(R.id. bubble_me_text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Chat chat = mData.get(position);
if (chat.isMe) {
viewHolder.bubbleMe.setText(chat.message);
viewHolder.layoutMe.setVisibility(View.VISIBLE);
viewHolder.layoutYou.setVisibility(View.GONE);
} else {
viewHolder.bubbleYou.setText(chat.message);
viewHolder.nickname.setText(chat.nickname);
viewHolder.layoutMe.setVisibility(View.GONE);
viewHolder.layoutYou.setVisibility(View.VISIBLE);
}
convertView.setEnabled(false);
return convertView;
}
}
private static class ViewHolder {
LinearLayout layoutMe;
LinearLayout layoutYou;
TextView nickname;
TextView bubbleYou;
TextView bubbleMe;
}
}
class ReceiverThread extends Thread {
interface OnReceiveListener {
void onReceive(String message);
}
OnReceiveListener mListener;
public void setOnReceiveListener(OnReceiveListener listener) {
mListener = listener;
}
Socket socket;
public ReceiverThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d("receiver", "run: ");
while (true) {
String str = reader.readLine();
if (mListener != null) {
mListener.onReceive(str);
}
}
} catch (Exception e) {
Log.e("chat", "run: " + e.getMessage());
}
}
}
/**
* 메시지의 발신을 담당하는 스레드 입니다.
*/
class SenderThread extends Thread {
Socket socket;
String name;
private PrintWriter mWriter;
public SenderThread(Socket socket, String name) {
this.socket = socket;
this.name = name;
}
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(final String message) {
new Thread(new Runnable() {
@Override
public void run() {
mWriter.println(message);
mWriter.flush();
}
}).start();
}
@Override
public void run() {
try {
// BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
mWriter = new PrintWriter(socket.getOutputStream());
// 제일 먼저 서버로 대화명을 송신합니다.
mWriter.println(name);
mWriter.flush();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
# activity_chat.xml
<?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:id="@+id/activity_chat"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.myapplication.activities.ChatActivity">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#00e5ff"
android:divider="@android:color/transparent"
android:transcriptMode="alwaysScroll" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/message_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="메세지를 입력하세요" />
<Button
android:id="@+id/send_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="보내기" />
</LinearLayout>
</LinearLayout>
26일차 RecyclerView
# EventBus (콜백 전달)
https://github.com/greenrobot/EventBus
# RecyclerView로 목록 만들기
https://developer.android.com/guide/topics/ui/layout/recyclerview#java
# RecyclerViewActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/RecyclerViewActivity.java
# activity_recycler_view.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_recycler_view.xml
# item_text.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/item_text.xml
public class RecyclerViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
List<String> data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
data.add("data " + i);
}
MyRecyclerAdapter adapter = new MyRecyclerAdapter(data);
recyclerView.setAdapter(adapter);
}
/**
* EventBus 에서 보내는 이벤트 수신하는 콜백 메서드
* @param event
*/
@Subscribe
public void onItemClick(ItemClickEvent event) {
Toast.makeText(this, "" + event.position, Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
super.onStart();
// EventBus에 구독자로 현재 액티비티 추가
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
// EventBus에 구독자에서 제거
EventBus.getDefault().unregister(this);
}
/**
* EventBus 에서 발송할 이벤트
*/
private static class ItemClickEvent {
View view;
int position;
}
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public ViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text_text);
}
}
private static class MyRecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
private final List<String> mData;
public MyRecyclerAdapter(List<String> dataList) {
mData = dataList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_text, parent, false);
return new ViewHolder(convertView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.textView.setText(mData.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// EventBus를 통해 이벤트 발송
// RecyclerViewActivity#onItemClick
ItemClickEvent event = new ItemClickEvent();
event.view = holder.itemView;
event.position = position;
EventBus.getDefault().post(event);
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
}
}
# activity_recycler_view.xml
<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:id="@+id/activity_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" />
</RelativeLayout>
# item_text.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:text="ddd"
android:id="@+id/text_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>