프로젝트 [코테 복습] - 문제 목록 조회

유의선·2024년 2월 29일

문제 목록 조회 Activity를 만들며, 데이터베이스, 기존 프래그먼트 등 몇 가지 부분을 수정하였다.


데이터베이스 수정

날짜로 문제를 조회할 때, 데이터베이스에 DATE 타입으로 저장한 속성을 불러올 방법을 몰라
데이터베이스의 DATE 저장 타입을 DATE에서 TEXT로 바꾸었다.

            String CREATE_SQL = "create table " + TABLE_TEST + "("
                    + " _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
                    + " DATE TEXT, "
                    + " TITLE TEXT, "
                    + " IMAGE TEXT, "
                    + " LINK TEXT "
                    + ")";

문제 복습 프래그먼트 수정

기존에는 onResume()에 바로 문제를 화면에 띄워주도록 만들었지만,
이 프래그먼트를 다른 곳에도 사용할 필요가 있어
onResume()의 내용을 비우고, 프래그먼트 밖에서 문제를 띄워주도록 만들었다.

날짜를 통해 문제를 조회/보여주는 함수와, id를 통해 문제를 조회/보여주는 함수를 만들었다.

    public void setTest(String dateInput){

        date = dateInput;

        TestDatabase database = TestDatabase.getInstance(getContext());

        String sql = "select * from " + TestDatabase.TABLE_TEST + " where DATE = '" + date + "'";

        if(database != null){
            Cursor cursor = database.rawQuery(sql);

            if(cursor.getCount() == 0){
                Toast.makeText(getContext(), "해당 날짜에 저장된 문제가 없습니다.", Toast.LENGTH_SHORT).show();
            }else{
                cursor.moveToNext();

                textDate.setText(date);

                title = cursor.getString(2);
                textTitle.setText(title);

                imageAddress = cursor.getString(3);
                try{
                    bitmap = BitmapFactory.decodeFile(imageAddress);
                    imageView.setImageBitmap(bitmap);
                }catch (Exception e){
                    Toast.makeText(getContext(), "이미지를 불러오는데 실패했습니다.", Toast.LENGTH_SHORT).show();
                }

                answerLink = cursor.getString(4);
            }
        }
    }

    public void setTest(int id){

        TestDatabase database = TestDatabase.getInstance(getContext());

        String sql = "select * from " + TestDatabase.TABLE_TEST + " where _id = '" + id + "'";

        if(database != null){
            Cursor cursor = database.rawQuery(sql);

            if(cursor.getCount() == 0){
                Toast.makeText(getContext(), "해당 날짜에 저장된 문제가 없습니다.", Toast.LENGTH_SHORT).show();
            }else{
                cursor.moveToNext();

                date = cursor.getString(1);
                textDate.setText(date);

                title = cursor.getString(2);
                textTitle.setText(title);

                imageAddress = cursor.getString(3);
                try{
                    bitmap = BitmapFactory.decodeFile(imageAddress);
                    imageView.setImageBitmap(bitmap);
                }catch (Exception e){
                    Toast.makeText(getContext(), "이미지를 불러오는데 실패했습니다.", Toast.LENGTH_SHORT).show();
                }

                answerLink = cursor.getString(4);
            }
        }
    }

리스트에 들어갈 Item

리스트에 들어갈 Item을 만들었다.

데이터베이스에 저장되는 내용을 그대로 저장하도록 만들었다.

public class Test implements Parcelable {
    int id;
    String date;
    String title;
    String question;
    String link;

    public Test(int id, String date, String title, String question, String link) {
        this.id = id;
        this.date = date;
        this.title = title;
        this.question = question;
        this.link = link;
    }

    public Test(Parcel src){
        id = src.readInt();
        title = src.readString();
        question = src.readString();
        link = src.readString();
    }

    public int getid() {
        return id;
    }

    public void setid(int num) {
        this.id = num;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }


    public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){
        public Test createFromParcel(Parcel in){
            return new Test(in);
        }
        public Test[] newArray(int size){
            return new Test[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(date);
        dest.writeString(title);
        dest.writeString(question);
        dest.writeString(link);
    }
}

이전 프로젝트에서 사용한 코드를 거의 그대로 사용하였다.


리스트 프래그먼트

문제 목록을 보여주는 프래그먼트를 만들었다.

리사이클러뷰에 위의 Item들을 데이터베이스에서 데이터를 가져와 그 제목을 보여주도록 하였다.

public class ListFragment extends Fragment {

    RecyclerView recyclerView;
    TestAdapter adapter;

    int start, end;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_list, container, false);

        recyclerView = rootView.findViewById(R.id.RecyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new TestAdapter();

        adapter.setOnItemClickListener(new OnTestClickListener() {
            @Override
            public void onItemClick(TestAdapter.ViewHolder holder, View view, int position) {
                Test item = adapter.getItem(position);

                Intent intent = new Intent(getContext(), ListTActivity.class);

                intent.putExtra("id", item.getid());

                intent.putExtra("start", start);
                intent.putExtra("end", end);

                startActivity(intent);
            }
        });

        recyclerView.setAdapter(adapter);

        loadQuestionListData();

        return rootView;
    }

    // 리사이클러뷰에 문제 추가 메소드
    public void loadQuestionListData() {

        int recordCount = 0;

        String sql = "select _id, DATE, TITLE, IMAGE, LINK FROM " + TestDatabase.TABLE_TEST + " order by _id ASC";

        TestDatabase database = TestDatabase.getInstance(getContext());
        if(database != null){
            Cursor cursor = database.rawQuery(sql);

            recordCount = cursor.getCount();

            for(int i = 0; i < recordCount; i++){
                cursor.moveToNext();

                int _id = cursor.getInt(0);
                if(i == 0)
                    start = _id;
                if(i == recordCount -1)
                    end = _id;

                String Date = cursor.getString(1);
                String Title = cursor.getString(2);
                String Image = cursor.getString(3);
                String Link = cursor.getString(4);

                adapter.addItem(new Test(_id, Date, Title, Image, Link));
            }

            cursor.close();
            adapter.notifyDataSetChanged();
        }

    }
}

사용한 TestAdapter의 내용은 다음과 같다.

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> implements OnTestClickListener {

    ArrayList<Test> items = new ArrayList<Test>();
    OnTestClickListener listener;

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from((parent.getContext()));
        View itemView = inflater.inflate(R.layout.test_box, parent, false);

        return new ViewHolder(itemView, this);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Test item = items.get(position);
        holder.setItem(item);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    public void addItem(Test item){
        items.add(item);
    }
    public void deleteAllItem(){
        items.clear();
    }

    public void setItems(ArrayList<Test> items){
        this.items = items;
    }

    public Test getItem(int position){
        return items.get(position);
    }

    public void setItem(int position, Test item){
        items.set(position, item);
    }

    public void setOnItemClickListener(OnTestClickListener listener){
        this.listener = listener;
    }

    @Override
    public void onItemClick(ViewHolder holder, View view, int position) {
        if(listener != null){
            listener.onItemClick(holder, view, position);
        }
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public ViewHolder(View itemView, final OnTestClickListener listener){
            super(itemView);

            textView = itemView.findViewById(R.id.textView);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position= getAdapterPosition();

                    if(listener != null){
                        listener.onItemClick(ViewHolder.this, v, position);
                    }
                }
            });
        }

        public void setItem(Test item){
            textView.setText(item.getTitle());
        }
    }
}

OnTestClickListener 인터페이스는 다음과 같다.

public interface OnTestClickListener {
    public void onItemClick(TestAdapter.ViewHolder holder, View view, int position);
}

코드는 자문자답 앱에서 사용한 것을 거의 그대로 사용하였다.


문제 조회 화면

문제 리스트에서 Item을 클릭하는것으로 그 문제를 조회하는 액티비티로 이동한다.

문제 조회 화면은 문제 복습 프래그먼트와, 좌우이동/수정/삭제 버튼으로 구성하였다.

문제 조회 화면에선 현재 id로 문제 복습 프래그먼트의 문제 조회/확인 메소드를 사용하도록 해 문제를 보여주도록 만들었다.

public class ListTActivity extends AppCompatActivity {

    ReviewFragment reviewFragment;
    Button buttonDelete;
    Button buttonEdit;
    Button buttonBack;
    Button buttonNext;

    int id;

    int start;
    int end;

    Cursor cursor = null;

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

        reviewFragment = new ReviewFragment();
        buttonDelete = findViewById(R.id.buttonDelete);
        buttonEdit = findViewById(R.id.buttonEdit);
        buttonBack = findViewById(R.id.buttonBack);
        buttonNext = findViewById(R.id.buttonNext);

        getSupportFragmentManager().beginTransaction().replace(R.id.container, reviewFragment).commit();

        Intent intent = getIntent();

        if(intent != null){
            Bundle bundle = intent.getExtras();

            id = bundle.getInt("id");

            start = bundle.getInt("start");
            end = bundle.getInt("end");
        }

        initQuestion();

        if(id == start)
            buttonBack.setEnabled(false);
        if(id == end)
            buttonNext.setEnabled(false);

        buttonDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        buttonEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        buttonBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                cursor.moveToPrevious();
                setTest();

                if(id == start){
                    buttonBack.setEnabled(false);
                }else{
                    buttonBack.setEnabled(true);
                }

                if(id == end){
                    buttonNext.setEnabled(false);
                }else{
                    buttonNext.setEnabled(true);
                }
            }
        });

        buttonNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                cursor.moveToNext();
                setTest();

                if(id == start){
                    buttonBack.setEnabled(false);
                }else{
                    buttonBack.setEnabled(true);
                }

                if(id == end){
                    buttonNext.setEnabled(false);
                }else{
                    buttonNext.setEnabled(true);
                }
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        if(id == start)
            buttonBack.setEnabled(false);
        if(id == end)
            buttonNext.setEnabled(false);

        setTest();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(cursor != null){
            cursor.close();
            cursor = null;
        }

    }

    private void setTest(){
        reviewFragment.isList = true;

        reviewFragment.setTest(id);
    }

    private void initQuestion() {

        TestDatabase database = null;

        if(cursor != null){
            cursor.close();
            cursor = null;
        }

        database = TestDatabase.getInstance(this);

        String sql = "select _id" + TestDatabase.TABLE_TEST + " order by _id ASC";

        cursor = database.rawQuery(sql);

        int recordCount = cursor.getCount();

        for(int i = 0; i < recordCount; i++){
            cursor.moveToNext();

            int _id = cursor.getInt(0);

            if(_id == id){
                setTest();
                break;
            }
        }
    }
}

이전 프로젝트에서 사용한 코드를 응용해서 그런지 쓸데없이 Parceble로 만들었다던가, 사용하지 않는 메소드가 존재한다. 이런 부분은 나중에 삭제할수도 있다.

또한 SQL 데이터베이스에서 DATE 타입을 읽는 방법은 결국 알아내지 못해 TEXT 타입으로 바꾸었지만 방법을 알게 되면 다시 DATE 타입으로 바꿀지도 모른다.

아직 이렇게 만든 프래그먼트와 액티비티들에 접근하고 확인할 수 있는 MainActivity를 만들지 않아 지금 이 코드로 실행하면 에러가 발생할 수도 있다.

0개의 댓글