MainActivity
package com.leopard4.postinglist;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.leopard4.postinglist.adapter.PostingAdapter;
import com.leopard4.postinglist.model.Post;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ProgressBar progressBar;
FloatingActionButton fab;
final String URL = "https://block1-image-test.s3.ap-northeast-2.amazonaws.com";
RecyclerView recyclerView;
PostingAdapter adapter;
ArrayList<Post> postList = new ArrayList<>();
// 내가 실행한 액티비티로부터, 데이터를 다시 받아오는 경우에 작성하는 코드
public ActivityResultLauncher<Intent> launcher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) { // setResult()의 결과와 매핑된것.
// 액티비티를 실행한후, 이 액티비티로
// 돌아왔을때 할 일을 여기에 작성
// AddActivity가 넘겨준
// Post 객체를 받아서 원상복구 시키고
// 리스트에 넣어주고
// 화면 갱신 해준다.
if (result.getResultCode() == AddActivity.SAVE) {
Post post = (Post) result.getData().getSerializableExtra("post");
postList.add(0, post); // 리스트의 맨앞에 추가
adapter.notifyDataSetChanged(); // 화면 갱신
}
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("포스팅리스트"); // 이코드가 예전버전도 호환이 됨
progressBar = findViewById(R.id.progressBar);
fab = findViewById(R.id.fab);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// fab 버튼을 누르면, 새로운 액티비티를 띄운다.
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startAddActivity();
}
});
// 네트워크 통해서 데이터를 받아오고, 화면에 표시
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest request = new JsonObjectRequest( // 파라미터 총5개
Request.Method.GET,
URL + "/posting.json",
null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// 네트워크 호출이 끝나면, 프로그래스바를 화면에서 숨긴다.
progressBar.setVisibility(View.GONE);
try {
JSONArray data = response.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
Post post = new Post(
data.getJSONObject(i).getInt("userId"),
data.getJSONObject(i).getInt("id"),
data.getJSONObject(i).getString("title"),
data.getJSONObject(i).getString("body")
);
postList.add(post); // 리스트란 힙에있는 post객체의 위치값만 선으로 연결하는것
}
} catch (JSONException e) {
return;
}
// 데이터를 화면에 표시
adapter = new PostingAdapter(MainActivity.this, postList);
recyclerView.setAdapter(adapter);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// 네트워크 호출이 끝나면, 프로그래스바를 화면에서 숨긴다.
progressBar.setVisibility(View.GONE);
}
}
);
// 네트워크 호출할때, 프로그래스바를 화면에 보이게 한다.
progressBar.setVisibility(View.VISIBLE);
// 네트워크 호출
queue.add(request);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if(itemId == R.id.menuAdd){
// AddActivity 를 실행한다.
startAddActivity();
}
return super.onOptionsItemSelected(item);
}
// AddActivity 를 실행하는 함수 만든다.
// 기획문서가 자주 바뀌니, 똑같은 코드는 함수화 시키는게 좋다.
void startAddActivity(){
Intent intent = new Intent(MainActivity.this, AddActivity.class);
launcher.launch(intent);
}
}
AddActivity
package com.leopard4.postinglist;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.leopard4.postinglist.model.Post;
public class AddActivity extends AppCompatActivity {
EditText editTitle;
EditText editBody;
Button btnSave;
public static final int SAVE = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
getSupportActionBar().setTitle("포스팅 생성");
getSupportActionBar().setDisplayHomeAsUpEnabled(true); // 뒤로가기 버튼
editTitle = findViewById(R.id.editTitle);
editBody = findViewById(R.id.editBody);
btnSave = findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
savePosting();
}
});
}
@Override
public boolean onSupportNavigateUp() {
finish();
return super.onSupportNavigateUp();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.add, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if(itemId == R.id.menuSave){
savePosting();
}
return super.onOptionsItemSelected(item);
}
void savePosting(){
String title = editTitle.getText().toString().trim();
String body = editBody.getText().toString().trim();
if (title.isEmpty() || body.isEmpty()) {
Toast.makeText(AddActivity.this, "모두 입력해주세요", Toast.LENGTH_SHORT).show();
return;
}
Post post = new Post(title, body);
// post 를 인텐트에 담아서 메인액티비티로 전달하고
// 나를실행한 액티비티한테 데이터를 전달해 주는 코드
Intent intent = new Intent();
intent.putExtra("post", post);
setResult(SAVE, intent);
// 이 액티비티는 사라져야 한다.
finish();
}
}
Post (클래스)
package com.leopard4.postinglist.model;
import java.io.Serializable;
public class Post implements Serializable {
public int id;
public int userId;
public String title;
public String body;
public Post() {
}
public Post(String title, String body) {
this.userId = -1; // 임의로 -1로 설정 // 설정을 안하면 디폴트로 0으로 됨.
this.id = -1;
this.title = title;
this.body = body;
}
public Post(int id, int userId, String title, String body) {
this.id = id;
this.userId = userId;
this.title = title;
this.body = body;
}
}
PostingAdapter
package com.leopard4.postinglist.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.leopard4.postinglist.R;
import com.leopard4.postinglist.model.Post;
import java.util.ArrayList;
public class PostingAdapter extends RecyclerView.Adapter<PostingAdapter.ViewHolder>{
Context context;
ArrayList<Post> postList;
public PostingAdapter(Context context, ArrayList<Post> postList) {
this.context = context;
this.postList = postList;
}
@NonNull
@Override
public PostingAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.posting_low, parent, false);
return new PostingAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PostingAdapter.ViewHolder holder, int position) {
Post post = postList.get(position);
holder.txtTitle.setText(post.title);
holder.txtBody.setText(post.body);
}
@Override
public int getItemCount() {
return postList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView txtTitle;
TextView txtBody;
ImageView imgDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtBody = itemView.findViewById(R.id.txtBody);
txtTitle = itemView.findViewById(R.id.txtTitle);
imgDelete = itemView.findViewById(R.id.imgDelete);
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:targetSandboxVersion="1"> <!-- 에뮬레이터 네트워크 설정 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 실배포시 이부분만해주면 됩니다. -->
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config" <!-- 에뮬레이터 네트워크 설정 -->
android:supportsRtl="true"
android:theme="@style/Theme.PostingList"
android:usesCleartextTraffic="true" <!-- 에뮬레이터 네트워크 설정 -->
tools:targetApi="31">
<activity
android:name=".AddActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
https://github.com/leopard4/PostingList
'Android' 카테고리의 다른 글
Android [프로필 리사이클앱] 이미지 레이아웃 배치 / 선택한 이미지 크게보기 (0) | 2023.02.07 |
---|---|
Android 이미지 처리를 위한 Glide 라이브러리 사용법 (0) | 2023.02.07 |
Android [회사직원관리앱] 양방향통신 launcher가 안될때/ 액션바 메뉴/ fab / 네트워크 프로그래스바 (0) | 2023.02.06 |
Android 네트워크 통신 (0) | 2023.02.03 |
Android [메모앱/서치/리사이클] maxline, ellipsize, addTextChangedListener, github 올리기 (0) | 2023.02.03 |