마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

막히던 기능 구현을 했는데 피드백좀 해주시면 감사하겠습니다(장문)

0 추천

-메인화면

 

-한줄평 작성하기 화면

 

-한줄평 모두보기 화면

 

안녕하세요?

바로 기능 설명을 드리자면 

메인화면(첫번째사진)에는 한줄평 아이템들이 보입니다 (리사이클러뷰 구현, 보이는 아이템 갯수 2개 제한)

작성하기(두번째사진)에서 작성한 멘트를 추가할 수 있습니다 (보이는 아이템 갯수는 2개제한이라

내부적으로만 추가됨)

모두보기(세번째)를 하면 모든 멘트들을 볼 수 있습니다. 모두보기에서도 작성하기 기능이 있습니다.

두번째 사진과 똑같고 기능도 똑같습니다. 모두보기에서 작성하기를 하면 모두보기에서 추가한 것이므로

여기는 바로 추가된 아이템이 보입니다.

-----------------------------------------------------------------------여기까지가 기능입니다.

기능이 어떻게 작동하는지와 문제점입니다

1. 메인액티비티에서 인텐트를 이용해 startActivtyForResult()를 사용해 작성하기화면을 띄우고

데이터를 받음. 모두보기의 작성하기도 마찬가지.

2. 받은 데이터를 아이템에 추가하고 모든 데이터를 '모두보기 액티비티'에 putParcelableArrayExtra()를 이용

보낸후 모두보기 액티비티에서는 모든 아이템이 정상적으로 보임.

3. '모두보기' 액티비티에서 작성하기를 이용해 아이템을 추가하면 '모두보기'에는 정상적으로 추가되어

아이템들이 보이나, 모두보기에서 뒤로가기를 누른 후 다시 메인 액티비티에서 모두보기를 들어가면

방금 모두보기화면을 통해 작성했던 아이템은 안보임. (문제점)

(예상) -> 메인액티비티에서 모두보기를 클릭시 Parcelable을 이용해 모든 객체를 전달해 보이는 방식인데, 

'모두보기 액티비티'는 메인액티비티로 받은 전체 아이템에다가 '모두보기'의 작성하기를 통해 추가했으므로

모두보기 화면에는 정상적으로 보이지만, '모두보기'의 작성하기를 통해

추가된 데이터는 '모두보기'의 아이템리스트에만 추가가 된것이므로 뒤로가기를 누르게 되면

메인액티비티에는 모두보기의 작성하기를 통해  전달받은 데이터가 없으므로  다시 모두보기를 누르면

원래 가지고 있던 아이템리스트만 전달하게 된것이니 모두보기 확면은 모두보기의 작성하기를 통해

추가한 데이터가 없어지게됨

---------

생각한 해결책으로는 모두보기의 작성하기를 통해 데이터를 모두보기 액티비티에서 받으면

이 데이터를 다시 메인 액티비티로 보내서 아이템리스트에 추가하는 것입니다.

메인액티비티든, 모두보기 액티비티든 인텐트를 통해 화면을 띄우고 onActivityResult()를 통해

데이터를 받아오므로 '모두보기'의 작성하기에서 onActivityResult()를 통해 받아온 데이터를 

메인 액티비티의 onActivityResult()를 호출해서 데이터를 전달하는 것입니다

메인onActivityResult()를 호출할때는 메인액티비티의 화면을 띄울 필요가 없으므로 

액티비티만 참조해서(https://jhshjs.tistory.com/17) 호출하도록 했습니다

 

MainActivity.class (메인 액티비티)

public class MainActivity extends AppCompatActivity {
    ArrayList<CommentItem> items;
    public static Context mainActivity; // 메인액티비티를 참조할 객체

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainActivity = this; // 메인 액티비티 참조

        recyclerView.setLayoutManager(layoutManager);
        adapter = new ItemAdapter();
        items = new ArrayList<>();

        items.add(new CommentItem("테스트1","가나다라마바사1","10분전"));
        items.add(new CommentItem("테스트2","가나다라마바사2","13분전"));
        items.add(new CommentItem("테스트3","가나다라마바사2","13분전"));

        ShowItems(); // 아이템 2개까지만 보이게 하기
        recyclerView.setAdapter(adapter);

        // 작성하기 버튼
        writeComment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), WriteComment.class);
                startActivityForResult(intent,101); // 작성하기 화면 띄우기
            }
        });

        // 모두보기 버튼
        seeAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), SeeAll.class);
                intent.putParcelableArrayListExtra("data", items);
                startActivity(intent);
            }
        });
    }

    // 작성한 한줄평 데이터 받아와서 추가하기
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 101) {
            if(data != null) {
                String comment = data.getStringExtra("comment");
                if(comment != null) {
                    items.add(new CommentItem("테스터" + count, comment, "지금막"));
                }
            }
        }
    }
}

WriteComment.class (작성하기)

public class WriteComment extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.write_comment);

        // 한줄평 저장하기
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String check = write.getText().toString();
                Intent intent = new Intent();
                // 아무것도 입력하지 않았을때
                if(check.equals("")) {
                    Toast.makeText(getApplicationContext(),"내용을 입력해주세요",Toast.LENGTH_LONG).show();
                }
                // 내용 저장할때
                else {
                    intent.putExtra("comment", write.getText().toString()); // 작성한 데이터 넣기
                    setResult(RESULT_OK, intent); // 데이터 보내기
                    finish();
                }
            }
        });
}

 

SeeAll.class (모두보기)

public class SeeAll extends AppCompatActivity {
    ArrayList<CommentItem> items;
    Intent intent; // onActivityResult() 데이터 받을 인텐트이자 메인액티 티에 보낼 인텐트

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.see_all);

        writeComment = findViewById(R.id.write_comment);
        recyclerView = findViewById(R.id.rv);
        
        recyclerView.setLayoutManager(layoutManager);

        // MainActivity에서 보내온 아이템 받기
        items = getIntent().getParcelableArrayListExtra("data");
        adapter = new ItemAdapter();
        adapter.setItems(items);
        recyclerView.setAdapter(adapter);

        // 작성하기
        writeComment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), WriteComment.class);
                startActivityForResult(intent,201); // 작성하기 화면 띄우기
            }
        });
    }

    // 뒤로가기, 메인액티비티에 작성하기로 추가한 데이터 전달하기
    @Override
    public void onBackPressed() {
        int requestCode = 101;
        int resultCode = RESULT_OK;
        // 메인액티비티 onActivityResult() 호출
        ((MainActivity) MainActivity.mainActivity).onActivityResult(requestCode, resultCode, intent);
        recyclerView.setAdapter(adapter);
        finish();
    }

    @Override // 작성하기 데이터 받아오기
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        intent = data; // 작성하기에서 받아온 데이터 저장
        if(requestCode == 201) {
            if(data != null) {
                String comment = data.getStringExtra("comment");
                if(comment != null) {
                    count += 1;
                    adapter.addItem(new CommentItem("모두테스터" + count, comment, "지금막"));
                    recyclerView.setAdapter(adapter);
                }
            }
        }
    }
}

 

codeslave (3,940 포인트) 님이 2020년 9월 17일 질문
codeslave님이 2020년 9월 17일 수정

1개의 답변

0 추천
/*
    삭제
// 뒤로가기, 메인액티비티에 작성하기로 추가한 데이터 전달하기
    @Override
    public void onBackPressed() {
        supoer.onBackPressed()
    }
*/

private void setResultAndFinish() {
      setResult(RESULT_OK)
      finish();
}

 onBackPressed() 콜백은 안거드리시는 게 좋구요. 확인버튼을 눌렀을 때만 전달할 데이터를 세팅하시면 됩니다. 사용자가 아무 액션도 안취했다면 굳이 결과를 세팅안하셔도 됩니다. 어차피 이전 MainActivity 사용자가 취소했는지 확인버튼을 눌렀는지 체크가 가능하니까요.

 

SeeAll: 이름이 헷갈립니다. 클래스 이름만 봐서는 이게 액티비티인지 모르겠고 동사를 사용하고 있어서 자바의 명명규칙에 위배됩니다. 클래스는 명사를 사용하셔야 해요. 남들이 봐도 아 이 클래스는 뭐를 하는 클래스이다를 예측 가능하도록 하는 적절한 명명은 좋은 코드를 만들기 위해서 아주 중요합니다. 좀더 명확한 이름을 선택해 보세요. 예를 들면,

SeeAll -> MoviewReviewListActivity or MovieReviewActivity

 

코멘트 대신에 명료한 이름을 가진 메소드를 사용하시는 게 훨씬 낫습니다. 예를 들면,

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCrete(savedInstanceState);

    ...

    initMovieItemsWithParcel();
}

private void initMovieItemsWithParcel() {
      items = getIntent().getParcelableArrayListExtra("data");
      adapter = new ItemAdapter();
      adapter.setItems(items);
      recyclerView.setAdapter(adapter);  
}

 

 

안드로이드  ResultApi를 이용하시면 onActivityResult 콜백없이 직관적인 코드를 작성할 수 있습니다.

https://developer.android.com/training/basics/intents/result

val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
    // Handle the returned Uri
}

 

spark (227,470 포인트) 님이 2020년 10월 11일 답변
spark님이 2020년 10월 11일 수정
오오... 예전질문인데.. 감사합니다!!
...