Работа с Realm в ViewHolder

196
15 января 2018, 08:48

Не могу реализовать функцию избраное в бд Realm. Опыта с ORM ранее не имел поэтому прошу извенить за вопрос. Код:

...
private Realm mRealmDatabase = Realm.getDefaultInstance();
private RealmResults<Invoice> mInvoices = mRealmDatabase.where(Invoice.class).findAllAsync();
...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
        mInvoices.addChangeListener(new RealmChangeListener<RealmResults<Invoice>>() {
            @Override
            public void onChange(RealmResults<Invoice> invoices) {
                mInvoices = invoices;
                mInvoiceAdapter.notifyDataSetChanged();
            }
        });
        setupAdapter();
        return view;
    }

     private class InvoiceViewHolder extends RecyclerView.ViewHolder
                                            implements View.OnClickListener,
                                                       PopupMenu.OnMenuItemClickListener {
    //view holder
...
    public void bindInvoiceItem(Invoice invoice){
               mInvoice = invoice;
               mTitleTextView.setText(invoice.getName());
               syncColorFavoriteButton(mInvoice.getIsFavorite());
          }
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.popup_menu_button:
                    mPopupMenu = new PopupMenu(getActivity(), mPopupMenuButton);
                    mPopupMenu.setOnMenuItemClickListener(this);
                    mPopupMenu.inflate(R.menu.card_popup_menu);
                    mPopupMenu.show();
                    break;
                case R.id.favorite_image_view:
                    syncColorFavoriteButton(isFavorite);
                    mRealmDatabase.executeTransactionAsync(new Realm.Transaction() {
                        @Override
                        public void execute(Realm realm) {
                            isFavorite = !isFavorite;
                            mInvoice.setIsFavorite(isFavorite);
                        }
                    }, new Realm.Transaction.OnSuccess() {
                        @Override
                        public void onSuccess() {
                            Toast.makeText(getActivity(), "is done!", Toast.LENGTH_LONG).show();
                        }
                    });
                    break;
            }
        }
private void syncColorFavoriteButton(boolean isFavorite){
   if (isFavorite){
       mIsFavoriteButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_invoice_tab_enabled));
   }else {
       mIsFavoriteButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_invoice_tab_disabled));
   }
  }
}

В результате при нажатии на кнопку Добавить в избраное получаю ошибку:

 FATAL EXCEPTION: main
                                                                                     Process: com.example.admin.personnelefficiency, PID: 8302
                                                                                     io.realm.exceptions.RealmException: Async transaction failed
                                                                                         at io.realm.Realm$1$2.run(Realm.java:1558)
                                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                         at android.os.Looper.loop(Looper.java:148)
                                                                                         at android.app.ActivityThread.main(ActivityThread.java:7325)
                                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
                                                                                      Caused by: java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
                                                                                         at io.realm.BaseRealm.checkIfValid(BaseRealm.java:426)
                                                                                         at io.realm.InvoiceRealmProxy.realmSet$isFavorite(InvoiceRealmProxy.java:247)
                                                                                         at com.example.admin.personnelefficiency.model.model.Invoice.setIsFavorite(Invoice.java:51)
                                                                                         at com.example.admin.personnelefficiency.model.fragments.InvoiceListFragment$InvoiceViewHolder$1.execute(InvoiceListFragment.java:127)
                                                                                         at io.realm.Realm$1.run(Realm.java:1502)
                                                                                         at io.realm.internal.async.BgPriorityRunnable.run(BgPriorityRunnable.java:34)
                                                                                         at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
                                                                                         at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                                         at java.lang.Thread.run(Thread.java:818)
Answer 1

У вас проблема в том, что ваши данные находятся в главном потоке, а в транзакции у вас другой поток и в нём трогать данные нельзя. Данные можно трогать только в том потоке, в котором они получены.

Т.е. вам надо в транзакции вытащить по ID данные и их и менять. Примерно так:

String id = mInvoice.getId();
mRealmDatabase.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        isFavorite = !isFavorite;
        Invoice inDbInvoice = realm.where(Invoice.class).equalTo("id",id).findFirst();
        inDbInvoice.setIsFavorite(isFavorite);
    }
}, new Realm.Transaction.OnSuccess() {
    @Override
    public void onSuccess() {
        Toast.makeText(getActivity(), "is done!", Toast.LENGTH_LONG).show();
    }
});

После изменения записи в БД у вас автоматом обновится выборка из оной и обновится адаптер с уже новыми данными

READ ALSO
org.apache.axis.wsdl.toJava.DuplicateFileException: Duplicate file name

org.apache.axis.wsdl.toJava.DuplicateFileException: Duplicate file name

Пытаюсь распарсить wsdl в RPC/Encoding стиле с помощью утилиты h WSDL2Java от Apache Axis 14

217
Работа со строками и файлами

Работа со строками и файлами

Как в стек записать строки и вывести их в файл в обратном порядке на java?

253
Не получается выписать нужные данные из всех объектов одного класса в текстовый документ

Не получается выписать нужные данные из всех объектов одного класса в текстовый документ

При воспроизведению программы создается текстовый файл, в котором записываются сначала все данные о объектахПосле чего при нажатии на кнопку...

293
java.util.InputMismatchException и как с ним бороться

java.util.InputMismatchException и как с ним бороться

Доброго времени сутокРешаю задачу, нужно ввести с клавиатуры 2 числа, одно типа int, второе с плавающей точкой, т

221