3월 17일
오늘 배운 것
- TODO프로젝트 이용해서 Todo App 만들기 (8)
LocalDate 변환하기
String -> LocalDate 클래스 만들기
public class LocalDateDeserializer implements JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
LocalDate localDate = LocalDate.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
return localDate;
} // deserialize
}
LocalDate -> String 클래스 만들기
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
String strDate = FORMATTER.format(src);
return new JsonPrimitive(strDate);
Retrofit 생성 시 변환 클래스 추가
private static Retrofit getInstance() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateSerializer());
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer()); // 서버에서 넘어오는 문자열 변환
Gson gson = gsonBuilder.setPrettyPrinting().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.219.104:8090") // localhost 사용할 수 없기 때문에 ip주소를 적어준다
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit;
} // getInstance
}
TodoRestServlet 서버에도 변환 메소드 추가
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("TodoRestServlet init() 호출됨");
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateSerializer());
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer());
gson = gsonBuilder.setPrettyPrinting().create(); // json 줄바꿈 출력
}
각 item 뷰
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tvTodoMeMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="데이터가 없습니다."
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
public class LocalDateDeserializer implements JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
LocalDate localDate = LocalDate.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
return localDate;
} // deserialize
}
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
String strDate = FORMATTER.format(src);
return new JsonPrimitive(strDate);
private static Retrofit getInstance() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateSerializer());
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer()); // 서버에서 넘어오는 문자열 변환
Gson gson = gsonBuilder.setPrettyPrinting().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.219.104:8090") // localhost 사용할 수 없기 때문에 ip주소를 적어준다
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit;
} // getInstance
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("TodoRestServlet init() 호출됨");
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateSerializer());
gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer());
gson = gsonBuilder.setPrettyPrinting().create(); // json 줄바꿈 출력
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tvTodoMeMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="데이터가 없습니다."
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
새 할 일 추가버튼 만들기, 이름과아이디 알려주기
버튼 클릭 시 loginId 값을 bundle 객체에 넣고 할 일 추가화면으로 이동
btnTodoAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MainActivity mainActivity = (MainActivity) getActivity();
Bundle extraBundle = new Bundle();
extraBundle.putString("loginId", loginId);
mainActivity.onFragmentChanged(MainActivity.TODO_ADD, extraBundle);
}
});
할 일을 띄움과 동시에 TextView에 이름과 아이디 출력하기
private void setTodosAndShow(TodoListResult todoListResult) {
// 응답받은 Result 객체에서 데이터 꺼내기
User user = todoListResult.getUser();
String username = user.getFirstName() + " " + user.getLastName() + " (" + user.getUserName() + ")";
tvUsername.setText(username);
List<Todo> todoList = user.getTodolist();
// Todo(할일) 데이터 존재여부 확인
if (todoList == null || todoList.size() == 0) {
tvTodoMeMsg.setVisibility(View.VISIBLE);
return;
}
tvTodoMeMsg.setVisibility(View.GONE);
// Adapter에 데이터 설정하기
// for (Todo todo : todoList) {
// adapter.addItem(todo);
// }
adapter.setItems(todoList);
// Adapter에 데이터 갱신 알리기 (recyclerView가 변경된 데이터로 아이템뷰를 다시 화면에 그려줌)
adapter.notifyDataSetChanged();
}// setTodosAndShow
새 할 일 추가화면
- spinner로 진행중, 완료 현재상태 표시하도록 설정하기
- 날짜 선택 칸 터치 시 날짜 선택 창이 나타나도록 설정하고 입력형식 설정하기
- 서버연결 지연으로 응답이 늦어질 경우를 대비해서 progressDialog로 처리중임을 나타내기
- 성공적으로 서버전송 처리 시 progressDialog 닫고 내 할 일 페이지로 이동하기
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.Button;
import android.widget.DatePicker;
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.MainActivity;
import com.example.todo.R;
import com.example.todo.domain.Todo;
import com.example.todo.domain.TodoResult;
import com.example.todo.retrofit.RetrofitClient;
import com.example.todo.retrofit.TodoService;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class TodoAddFragment extends Fragment {
public static final String TAG = "TodoAddFragment";
private EditText txtTitle, txtDescription, txtTargetDate;
private String loginId;
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_add,container, false );
// Bundle 객체 참조 가져오기
Bundle bundle = getArguments();
loginId = bundle.getString("loginId");
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[] {"진행중", "완료"}
);
// 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 띄우기기
datePickerDialog.show();
}
return false;
}
});
// 현재 년,월,일 값구하기
Calendar calendar = Calendar.getInstance();
int nowYear = calendar.get(Calendar.YEAR);
int nowMonth = calendar.get(Calendar.MONTH); // 영미권은 0~11, 출력할 때는 +1을 해줘야함 (ex 1월 = 0, 2월 = 1)
int nowDay = calendar.get(Calendar.DAY_OF_MONTH);
//날짜선택 대화상자 준비하기
datePickerDialog = new DatePickerDialog(getContext(), new DatePickerDialog.OnDateSetListener() {
@Override // 최종 결정할 때 호출됨
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
String strDate = "";
strDate += year;
strDate += "-" + String.format("%02d", month + 1); // 2자리 숫자로 만드는데 한자리면 앞에 0을 붙임
strDate += "-" + String.format("%02d", day);
txtTargetDate.setText(strDate);
}// onDateSet
},nowYear, nowMonth, nowDay);
// progressDialog 설정하기
progressDialog = new ProgressDialog(getContext());
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setMessage("처리 중 입니다....");
// 할 일 저장 버튼 클릭 이벤트 연결
Button btnTodoSave = view.findViewById(R.id.btnTodoSave);
btnTodoSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
btnTodoSave.setEnabled(false); // 버튼 비활성화
progressDialog.show(); // 로딩 중
requestAddTodo(); // 서버에 새 Todo 등록
}
});
return view;
} // onCreateView
private void requestAddTodo() {
String title = txtTitle.getText().toString().trim();
String description = txtDescription.getText().toString().trim();
String strStatus = (String) spinnerStatus.getSelectedItem();
String strDate = txtTargetDate.getText().toString().trim();
// localDate 변환
LocalDate localDate = LocalDate.parse(strDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 추가할 Todo 객체 준비
Todo todo = new Todo();
todo.setUsername(loginId);
todo.setTitle(title);
todo.setDescription(description);
todo.setStatus(strStatus.equals("완료")? true : false);
todo.setTargetDate(localDate);
Log.d(TAG, "todo : " + todo.toString());
TodoService todoService = RetrofitClient.getTodoService();
Call<TodoResult> call = todoService.addTodo(todo);
call.enqueue(new Callback<TodoResult>() {
@Override
public void onResponse(Call<TodoResult> call, Response<TodoResult> response) {
if (!response.isSuccessful()) {
Log.d(TAG,"onResponse : " + response.message());
return;
}
TodoResult todoResult = response.body();
if (todoResult.isSuccess()) {
onResponseSuccess();
}
}
@Override
public void onFailure(Call<TodoResult> call, Throwable t) {
Log.d(TAG, "onFailure : " + t.getMessage());
}
});
}// requestAddTodo
private void onResponseSuccess() {
progressDialog.dismiss(); // progressDialog 닫기
Bundle bundle = new Bundle();
bundle.putString("loginId", loginId);
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.onFragmentChanged(MainActivity.TODO_ME, bundle);
}// onResponseSuccess
}
Author And Source
이 문제에 관하여(3월 17일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@tutu10000/3월-17일저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)