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

데이터가 mysql에 저장되어 있으면 체크 상태를 true로 유지하고 싶습니다.

0 추천

안드로이드에서 listview로 목록이 출력되고 목록들 중 체크한 항목을 db에 저장하도록 구현하였습니다.

mysql에 체크한 정보에 제목, 내용, ID 값이 저장되는데 ID 값이 db에 저장되어 있다면 안드로이드에서 체크상태를 true로 유지하고 싶습니다.  또한, 앱이 종료되었다 다시 실행되어도 이 상태를 유지하고 싶은데 가능한가요??

@Override
public View getView(int i, View view, ViewGroup parent) {
    Context context = parent.getContext();
    final ViewHolder holder;//아이템 내 view들을 저장할 holder 생성
    userID = ((MemberActivity)MemberActivity.context).userID;




    final PublicDataList publicDataList_item = publicDataLists.get(i);
    servID = publicDataList_item.getServID();


    Log.d(TAG, "items_adapter : " + publicDataLists.toString());


    //"item_list" Layout을 inflate하여 view 참조 획득
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //최초 생성 view인 경우, inflation -> ViewHolder 생성 -> 해당 View에 setTag 저장
        view = inflater.inflate(R.layout.parsing_list, parent, false);

        holder = new ViewHolder();

        //화면에 표시될 View(Layoutㅇ inflate된)으로부터 위젯에 대한 참조 획득
        holder.list_text_name = (TextView) view.findViewById(R.id.list_text_name);
        holder.list_text_content = (TextView) view.findViewById(R.id.list_text_content);

        //해당 view에 setTag로 Holder 객체 저장
        view.setTag(holder);
    } else {
        //view가 이미 생성된 적이 있다면, 저장되어 있는 Holder 가져오기
        holder = (ViewHolder) view.getTag();
    }

    holder.list_text_name.setText(publicDataList_item.getServNm());
    holder.list_text_content.setText(publicDataList_item.getServDgst());
    holder.servID = publicDataList_item.getServID();


    CheckBox add_favorite = (CheckBox)view.findViewById(R.id.add_favorite);

    add_favorite.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            boolean newState = !publicDataList_item.isChecked(); //check 면 uncheck로 uncheck 면 check로 바꿔 저장
            publicDataList_item.checked = newState;

            if(newState==true){
                FavoriteInsertData task = new FavoriteInsertData();
                task.execute(userID, holder.list_text_name.getText().toString(), holder.list_text_content.getText().toString(), holder.servID,String.valueOf(publicDataList_item.getChecked()));
            }
        }
    });
    return view;
}

 

추가한 부분

------------------------------------------------------------------------------------------------

아이템에 check상태를 저장하는 변수 선언했습니다.

public class PublicDataList {

    public String jurMnofNm;          // 단체
    public String lifeArray;          //생애주기
    public String servDgst;           // 내용
    public String servDtlLink;        // 링크
    public String servNm;             // 제목
    public String trgterIndvdlArray;  // 대상
    public String servID;             // 서비스 ID

    public boolean checked;

...
)

 

ddad (120 포인트) 님이 2022년 6월 5일 질문
ddad님이 2022년 6월 6일 수정

2개의 답변

0 추천
모발앱에서 사용가능한 데이터베이스는 SQLite뿐입니다. MySQL같은 데이터베이스는 서버용으로 여기에 접근하려면 바로 하지 못하고 웹서버를 통하여 JSON이라는 데이터포맷을 이용하여 서버가 서비스를 제공하는 형태로 이루어 집니다. 따라서 MySQL에 있는 데이터를 읽고 쓸려면 데이터베이스를 처리할 서버를 두고 이 서버에 PHP, NodeJS, J2EE(Spring)같은 랭귀지 또는웹프레임웤을 이용하여 서비스를 구축해야 합니다.

이럴 수 있는 여력이 안되시거나 귀찮은 분들이 서버의 구축없이 간단하게 서버 기능을 대신 제공하는 파이어베이스를 사용하기도 합니다. 파이어베이스도 데이터베이스가 제공되는데(Reatime DB 또는 Firestore) MySQL과 같은 RDBMS와는 상당히 다른 Document 기반의 JSON Tree입니다.

프로토타입이나 규모가 그리 크지않은 소규모 프로젝트에서 사용하기에는 적합하다고 보여집니다. 어느정도까지는 무료예요.

결론적으로, 먼저 REST API를 서버에서 구축하시고 이걸 이용하여 안드로이드 앱에서는 HTTP 통신을 해야 합니다. 이 때 안드로이드 앱에서 사용하는 것이 Volley, Retrofit과 같은 라이브러리입니다. 라이브러리가 없으면 상당히 많은 양을 코딩해야 하고, 에러가 날 가능성도 많이 존재하기 때문에 일반적으로는 개념을 이해한 후 라이브러리를 사용합니다.
spark (224,800 포인트) 님이 2022년 6월 6일 답변
wamp64 서버와 php 사용하고 있습니다.
이미 답을 드렸듯이 원하는 데이터를 처리할 수 있는 서비스를 만드시고 이걸 안드로이드앱에서 http통신으로 처리하세요.
현재 http통신으로 처리도 되고 있는 상태입니다. 다만, 체크 상태 유지를 어떻게 구현해야할지 모르겠습니다. ㅠㅠ
화면에 보여질 아이템에 해당하는 클래스가 있으실 거예요. 이 클래스에 체크상태를 나타낼 booelan를 추가 히시구요. 서버에서 데이터를 가져올 때 이 필드를 채워주시고, 화면을 업데이트 할 때는 이 필드를 읽어서 true일 때 뤈하시는 업데이트를 하세요.
체크박스를 누르면 체크상태로 변함과 동시에 db에 저장됩니다. 현재 코드에서는 onclicklistener를 사용하여 체크상태일 때 db에 저장하는 코드로 구현되어 있습니다. 위의 add_favorite.setonclicklistener부분이 이 부분입니다.
서버에서 데이터를 가져올 때 이 필드를 채워주시고, 화면을 업데이트 할 때는 이 필드를 읽어서 true일 때 뤈하시는 업데이트를 어떤 방식으로 해야할지 모르겠습니다...도와주세요...ㅠㅠ
0 추천

질문에 많은 정보가 빠져 있었네요.
체크박스 누를 때 DB에 저장을 하고 나면, 다시 서버에서 업데이트 된 정보를 가져와서 리스트뷰를 갱신해 주세요. 올리신 코드에 어댑터을 호출하는 부분이 없어서 임의대로 추측해서 코드를 적어 보겠습니다. 일부 클래스이름, 멤버변수 등은 가독성에 도움이 되는 방향으로 변경하였습니다.

public class PublicDataAdapter extends BaseAdapter {

    private static class ViewHolder {
        TextView titleTxt;
        TextView contentTxt;
        CheckBox favouriteCheck;
    }

    // 외부와의 interaction을 위해 Interface를 사용.
    interface Listener {
        void onAddFavourite(PublicDataItem item);
    }

    private final List<PublicDataItem> items = new ArrayList<>();

    private Listener listener;

    public void submitList(List<PublicDataItem> items) {
        this.items.clear();
        this.items.addAll(items);
        notifyDataSetChanged();
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

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

    @Override
    public PublicDataItem getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return items.get(position).hashCode();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = createHolderView(parent);
        }

        final PublicDataItem item = items.get(position);
        bindViewHolder(convertView, item);
        return convertView;
    }

    private void bindViewHolder(View convertView, PublicDataItem item) {
        final ViewHolder holder = (ViewHolder) convertView.getTag();
        holder.titleTxt.setText(item.getServNm());
        holder.contentTxt.setText(item.getServDgst());
        holder.favouriteCheck.setChecked(item.isChecked());
        holder.favouriteCheck.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Listener가 설정되었을 경우 Listener에 있는 메소드 호출.
                if (listener != null) listener.onAddFavourite(item); 
            }
        });
    }

    private View createHolderView(ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.item_public_data, parent, false);

        ViewHolder holder = new ViewHolder();
        holder.titleTxt = itemView.findViewById(R.id.titleTxt);
        holder.contentTxt = itemView.findViewById(R.id.contentTxt);
        holder.favouriteCheck = itemView.findViewById(R.id.favouriteCheck);
        itemView.setTag(holder);
        return itemView;
    }
}

핵심이 되는 어댑터의 코드입니다. 어댑터에서 발생하는 CheckBox 클릭 이벤트의 실제적인 처리는 어댑터가 할 일이 아니라 CheckBox를 누른 쪽의 역할입니다. 이 때문에 Listener 라는 인터페이스를 하나 선언하고 어댑터를 사용하는 쪽이 Listener인터페이스를 구현하도록 합니다.  이렇게 해야 어댑터도 재사용이 용이하고 호출하는 쪽에 이벤트 처리를 위임하므로 종속적이지 않는 코드가 됩니다.

public class PublicDataActivity extends AppCompatActivity {

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

        setupViews();
    }

    private final PublicDataAdapter publicDataAdapter = new PublicDataAdapter();

    private void setupViews() {
        ListView eventListView = findViewById(R.id.eventList);
        publicDataAdapter.submitList(getPublicDataItems());
        publicDataAdapter.setListener(new PublicDataAdapter.Listener() {
            @Override
            public void onAddFavourite(PublicDataItem item) {
                addFavourite(item);
            }
        });
        eventListView.setAdapter(publicDataAdapter);
    }

    private void addFavourite(PublicDataItem item) {
        // 이 코드는 데모 목적이므로, 실제로는 서버에 데이터를 저장하는 코드를 사용하셔야 겠죠?
        for (PublicDataItem element : demoData) {
            if (item.getServID().equals(element.getServID())) {
                element.setChecked(!element.isChecked());
                break;
            }
        }
        // 저장후 데이터를 다시 불러와 리스트뷰를 갱신
        publicDataAdapter.submitList(getPublicDataItems());
    }

    private final List<PublicDataItem> demoData = Arrays.asList(
            new PublicDataItem("1", "Title1", "Content1", false),
            new PublicDataItem("2", "Title2", "Content2", true),
            new PublicDataItem("3", "Title3", "Content3", false)
    );

    private List<PublicDataItem> getPublicDataItems() {
        // 데모 목적의 코드이므로, 실제로는 서버에서 데이터를 가져오는 코드를 사용할 것.
        return demoData;
    }
}

액티비티의 코드입니다. setupView에서 PublicDateAdapter.setListener를 호출하고 있습니다. addFavourite 메소드에서 데이터를 저장하는 부분이  asynchronous(비동기) 방식이면, 저장 작업이 끝난 후에 어댑터를 갱신하는 코드를 호출하셔야 겠죠.

spark (224,800 포인트) 님이 2022년 6월 6일 답변
참고로 어댑터 안에
userID = ((MemberActivity)MemberActivity.context).userID;

이런 식으로 어댑터 안에서 context를 타입캐스팅해서 특정 액티비티를 참조하는 건 좋지 않습니다. userId가 필요하면 외부에서 제공하세요.

public class MyAdapter extends BaseAdapter {
     private String userId;
     public void setUserId(String userId) {
          this.userId = userId;
     }
}
...