简体   繁体   中英

Android Realm Database not updating Record

I am new to Android Development i am trying to sort item position in Recyclerview i am useing Realm Database and my data-set for Adapter is RealmResults<ShoppingList>

here is my Adapter please take look my moveItemDown and updateItemPosition method im trying to update item position in updateItemPosition Method but it's not working. i also attached my view below the adapter

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private RealmResults<ShoppingList> dataList;
    private Realm mRealm;
    private LayoutInflater mInflater;

    public RecyclerAdapter(Context context, RealmResults<ShoppingList> data, Realm reamDatabaseInstence){
        this.dataList = data;
        this.mInflater = LayoutInflater.from(context);
        mRealm = reamDatabaseInstence;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.i("Recycler", "onCreateViewHolder");

        View view = mInflater.inflate(R.layout.shopping_list_item, parent,false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Log.i("Recycler", "onBindViewHolder " + position);

        ShoppingList currentItem = dataList.get(position);
        holder.setData(currentItem, position);
        holder.setListener();
    }

    public void moveItemDown(int position){
        if( position == (dataList.size()-1) ) { return; }
        int oi = position;
        int ni = position+1;
        updateItemPosition(oi, ni);
        notifyDataSetChanged();

    }

    public void moveItemUp(int position){
        // Need to implement after down sort work
    }

    private void updateItemPosition(final int pos, final int new_pos){
        mRealm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                ShoppingList old_item = realm.where(ShoppingList.class)
                        .equalTo("position", pos)
                        .findFirst();
                old_item.setPosition(new_pos);
                Log.d("UpdateData: ",old_item.getTitle()+" "+old_item.getPosition());

                ShoppingList new_item = realm.where(ShoppingList.class)
                        .equalTo("position", new_pos)
                        .findFirst();
                new_item.setPosition(pos);
                Log.d("UpdateData: ",new_item.getTitle()+" "+new_item.getPosition());

            }
        });
    }

    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        TextView title;
        ImageButton up, down;
        ImageView image;
        int position;
        ShoppingList current;

        MyViewHolder(View itemView) {
            super(itemView);
            title = (TextView) itemView.findViewById(R.id.shopping_card_view_title);
            image = (ImageView) itemView.findViewById(R.id.shopping_card_view_image);
            up = (ImageButton) itemView.findViewById(R.id.shopping_card_view_up_btn);
            down = (ImageButton) itemView.findViewById(R.id.shopping_card_view_down_btn);
        }

        void setData(ShoppingList i, int position) {
            title.setText( i.getTitle() );
            image.setImageResource(i.getImageId());
            this.position = position;
            this.current = i;
        }

        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.shopping_card_view_up_btn:
                    moveItemUp(position);
                    break;
                case R.id.shopping_card_view_down_btn:
                    moveItemDown(position);
                    break;
            }
        }

        void setListener() {
            up.setOnClickListener(MyViewHolder.this);
            down.setOnClickListener(MyViewHolder.this);
        }
    }

}

在此处输入图片说明

To get automatic updates, you should use RealmRecyclerViewAdapter from https://github.com/realm/realm-android-adapters

public class RecyclerAdapter extends RealmRecyclerViewAdapter<ShoppingList, RecyclerAdapter.MyViewHolder> { // <-- !
    private Realm mRealm;
    private LayoutInflater mInflater;

    public RecyclerAdapter(Context context, RealmResults<ShoppingList> data, Realm realm){
        super(data, true);
        this.mInflater = LayoutInflater.from(context);
        mRealm = realm;
    }

and replace dataList with getData()

It's late reply by it would help to you and this is the combination of both answer EpicPandaForce give a great example to work with RealmRecyclerViewAdapter and make your Recyclerview automated.

Second Option
this is to use UNIQUE ID FIELD in order to make changes in list item.

Here is the problem happening in you Code
Basically when you get an item by it's position for instance position=1; and you updated to position 2 right? notice now you have two item with same position = 2 and now when you try to get first item with position = 2 Realm return the same item that you updated from position 1 to 2 now what happening here you updated dated position back to position=1 ;

taman neupane give you good idea but he is not describe much.

Please TRY THIS

private void updateItemPosition(final int pos, final int new_pos){

    final String current_item_id = dataList.get(pos).get_id();
    final String new_item_id = dataList.get(new_pos).get_id();

    mRealm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            // Try to find the result with unique id replace this .equalTo("Your Unique ID Field name", current_item_id)
            ShoppingList old_item = realm.where(ShoppingList.class).equalTo("position", pos).findFirst();

            old_item.setPosition(new_pos);
            // Also here Try to find the result with unique id replace this .equalTo("Your Unique ID Field name", new_item_id)
            ShoppingList new_item = realm.where(ShoppingList.class).equalTo("position", new_pos).findFirst();

            new_item.setPosition(pos);
            //new you can tell you adapter about the changes in dataset.
            notifyItemMoved(pos, new_pos);
            notifyItemRangeChanged(pos, dataList.getSize());
        }
    });
}

and then update your both function with that

public void moveItemDown(int position){
    if( position == (dataList.size()-1) ) { return; }
    int oi = position;
    int ni = position+1;
    updateItemPosition(oi, ni);
}

public void moveItemUp(int position){
    if( position == 0 ) { return; }
    int oi = position;
    int ni = position-1;
    updateItemPosition(ni, oi);
}

And That's it. If anyone want to modify my explanation i will appreciate because i am not good in english.

Happy Coding.

I think your ShoppingList item has unique id for all. Just make id field primary and use realmInsertorUpdate feature . You don't have to check for any thing else. If the id is available it will update the database and if id is not available it will just insert.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM