기존의 할 일 추가화면을 이용해서 만들기
// item 클릭 이벤트 설정
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 선택된 아이템의 순서정보
int position = getAdapterPosition();
Todo todo = items.get(position);
Log.d(TAG, "선택 아이템 : " + todo.toString());
// 할일 수정, 삭제 화면으로 이동하기
long todoId = todo.getId();
Log.d(TAG, "선택 아이템 : " + todo.getId());
Bundle bundle = new Bundle();
bundle.putLong("id", todoId);
MainActivity mainActivity = (MainActivity) fragment.getActivity();
mainActivity.onFragmentChanged(MainActivity.TODO_MODIFY_REMOVE, bundle);
}
});
package com.example.todo.fragment.todo;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.example.todo.R;
import com.example.todo.domain.Todo;
import com.example.todo.domain.TodoOneResult;
import com.example.todo.retrofit.RetrofitClient;
import com.example.todo.retrofit.TodoService;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class TodoModifyRemoveFragment extends Fragment {
private static final String TAG = "TodoModifyRemoveFragment";
private long todoId;
private EditText txtTitle, txtDescription, txtTargetDate;
private Spinner spinnerStatus;
private DatePickerDialog datePickerDialog;
private ProgressDialog progressDialog; // 비동기 방식으로 동작함
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_todo_modify_remove, container, false);
//Bundle 객체 참조가져오기
Bundle bundle = getArguments();
todoId = bundle.getLong("id");
Log.d(TAG, "todoId : " + todoId);
txtTitle = view.findViewById(R.id.txtTitle);
txtDescription = view.findViewById(R.id.txtDescription);
txtTargetDate = view.findViewById(R.id.txtTargetDate);
spinnerStatus = view.findViewById(R.id.spinnerStatus);
// spinner 전용 Adapter라고 생각하면 됨
// android.R.layout.simple_spinner_item은 처음 보여지는 item
// android.R.layout.simple_spinner_dropdown_item 밑에 보여지는 item
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getContext(),
android.R.layout.simple_spinner_item,
new String[] {"진행중", "완료"} // index는 0 , 1
);
// Spinner 클릭 시 펼쳐질 layout 설정
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Spinner에 Adapter 설정
spinnerStatus.setAdapter(adapter);
// 날짜 선택 EditText에 Touch 이벤트 연결
txtTargetDate.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
// DatePickerDialog 띄우기기
if (datePickerDialog != null) {
datePickerDialog.show();
}
}
return false;
}
});
// progressDialog 설정하기
progressDialog = new ProgressDialog(getContext());
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setMessage("처리 중 입니다....");
requestGetTodoByTodoId(todoId);
return view;
} // onCreateView
private void requestGetTodoByTodoId(long todoId) {
TodoService todoService = RetrofitClient.getTodoService();
Call<TodoOneResult> call= todoService.getTodoById("one", todoId);
call.enqueue(new Callback<TodoOneResult>() {
@Override
public void onResponse(Call<TodoOneResult> call, Response<TodoOneResult> response) {
if (!response.isSuccessful()) {
Log.d(TAG,"onResponse : " + response.message());
return;
}
TodoOneResult todoOneResult = response.body();
if (todoOneResult.isHasResult()) {
Todo todo = todoOneResult.getTodo();
setTodoAndShow(todo);
}
}
@Override
public void onFailure(Call<TodoOneResult> call, Throwable t) {
Log.d(TAG,"onFailure : " + t.getMessage());
}
});
}// requestGetTodoByTodoId
private void setTodoAndShow(Todo todo) {
txtTitle.setText(todo.getTitle());
txtDescription.setText(todo.getDescription());
if (todo.isStatus()) { // true이면 완료
spinnerStatus.setSelection(1);
} else { // false이면 진행중
spinnerStatus.setSelection(0);
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String strDate = dateTimeFormatter.format(todo.getTargetDate());
txtTargetDate.setText(strDate);
progressDialog.dismiss();
}// setTodoAndShow
}// class TodoModifyRemoveFragment
이미지파일을 전송받으려면 서버에서 작업이 필요함
(이미지파일 뿐만 아니라 다른 종류의 파일들도 보낼 수 있지 않을까 싶음)
package todoApp.rest.todo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = "/displayImage", loadOnStartup = 1)
public class DisplayImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// (경로가 포함된) 이미지 파일명을 파라미터로 가져오기
String filename = request.getParameter("filename"); // leaf.png
// 파일 경로에 / 나 \\ 사용해야 잘못 인식하지 않는다.
File file = new File("C:/java502/Image", filename); // C:\java502\Image/leaf.png
if (!file.exists()) { // file 없으면
System.out.println("요청한 이미지 파일이 해당 경로에 존재하지 않습니다.");
return;
}
// 이미지 파일을 전송할것이기 때문에 image/png , image/gif 등 파일의 이미지 확장자가 출력됨
String contentType = Files.probeContentType(file.toPath());
response.setContentType(contentType);
// 입력스트림 객체 준비
BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
// 출력스트림 객체 준비
BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
int data;
while ((data = is.read()) != -1) { // -1이면 데이터 있음, 아니면 없음
os.write(data);
}// while
os.flush(); // 출력버퍼 비우기, 객체를 닫을 꺼면 없어도 됨
// 스트림 객체 닫기
is.close();
os.close();
} // doGet
}
아이템의 text설정 시 이미지파일도 같이 설정되게함
public void setItem(Todo item) {
if (item == null) {
return;
}
// 날짜 변환
LocalDate localDate = item.getTargetDate();
String strDate = localDate.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일"));
tvTitle.setText(item.getTitle());
tvDescription.setText(item.getDescription());
tvtvTagetDate.setText(strDate);
tvtvDone.setText(item.isStatus() ? "완료" : "진행중");
// Todo 객체 안에 이미지 파일명을 가져왔다고 가정
// ex) String filename = item.getImageFileName();
String filename = "leaf.jpg";
// 서버에 filename 이미지 요청하기
requestImage(filename);
}// setItem
private void requestImage(String filename) {
TodoService todoService = RetrofitClient.getTodoService();
Call<ResponseBody> call = todoService.downloadImage(filename);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (!response.isSuccessful()) {
Log.d(TAG, "onResponse : " + response.message());
return;
}
InputStream is = response.body().byteStream();
// 작업스레드에서 네트워크 스트림으로 이미지 읽어서 Bitmap객체 준비
// 네트워크 처리는 Thread 처리를 해서 병렬처리를 해야함
new Thread(() -> {
// 이미지 용량 줄이는 방법 1: 일정 배수로 이미지 용량 줄이기
// 읽어 올 때 용량을 줄여서 읽어옴
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // 이미지 크기를 4분의 1로 줄여서 읽어오도록 설정
// InputStream의 바이너리정보를 이미지객체로 변환
Bitmap bitmap = BitmapFactory.decodeStream(is,null, options);
// 이미지 용량 줄이는 방법 2 : 이미지뷰 크기로 이미지 용량 줄이기
// pixel 값으로 기기마다 다름
int width = img1.getWidth();
int height = img1.getHeight();
// 이미지용량이 클 경우 강제적으로 이미지 용량을 줄여야함
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
handler.post(() -> {
// UI 메인스레드에서 뷰에 접근함
// 이미지뷰에 사진 설정
img1.setImageBitmap(resizedBitmap);
});
}).start();
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d(TAG, "onFailure : " + t.getMessage());
}
});
}// requestImage
private void requestImage() {
Log.d(TAG, "requestImage 호출됨");
TodoService todoService = RetrofitClient.getTodoService();
Call<ResponseBody> call = todoService.downloadImage(filename);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (!response.isSuccessful()) {
Log.d(TAG, "onResponse : " + response.message());
return;
}
InputStream is = response.body().byteStream();
// 작업스레드에서 네트워크 스트림으로 이미지 읽어서 Bitmap객체 준비
// 네트워크 처리는 Thread 처리를 해서 병렬처리를 해야함
new Thread(() -> {
// 이미지 용량 줄이는 방법 1: 일정 배수로 이미지 용량 줄이기
// 읽어 올 때 용량을 줄여서 읽어옴
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // 이미지 크기를 4분의 1로 줄여서 읽어오도록 설정
// InputStream의 바이너리정보를 이미지객체로 변환
Bitmap bitmap = BitmapFactory.decodeStream(is,null, options);
// 이미지 용량 줄이는 방법 2 : 이미지뷰 크기로 이미지 용량 줄이기
// pixel 값으로 기기마다 다름
int width = imageProfile.getWidth();
int height =imageProfile.getHeight();
//
// // 이미지용량이 클 경우 강제적으로 이미지 용량을 줄여야함
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
runOnUiThread(()->imageProfile.setImageBitmap(resizedBitmap));
readyImgProfile = true;
}).start();
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d(TAG, "onFailure : " + t.getMessage());
}
});
}// requestImage