使用Realm进行数据操作(二)

Realm的异步操作

  在上一篇中使用了Realm的事务操作,实现了数据的增删改查。但是在执行增删改后,我们没法知道,数据是否发生改变了。反正我个人是比较菜,没找到啥方法能获取到数据是否发生改变。还好Realm本身支持异步操作并带有回调监听。使我又找到了学习的信心,然后实践了一下。

例子效果


Realm的异步任务(增、删、改)

  根据参考的资料来看,使用一个异步操作是挺简单的。因为步骤基本都是死的。基本步骤如下:

  • 1.声明一个全局变量(为啥用全局变量,因为如果我想要在界面销毁时,同时取消未完成的异步任务我只能这吗做!):
    private RealmAsyncTask insertTask,updataTask,deleteTask;//异步添加任务
  • 2.创建异步任务:
    创建RealmAsyncTask有四种方法,当然了它们都是重载方法。用哪个就看是啥需求了。
    创建异步任务

  这里与带三个参数的方法为例,我们来看一下这三个参数都是干嘛的。

        RealmAsyncTask task = realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                //执行异步操作-->执行线程子线程
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                //操作成功-->执行线程主线程
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                //操作失败-->执行线程主线程
            }
        });

  因为这三个参数都是接口的实现类同时还都是匿名内部类,所以还可以使用Lambda表达式进行一下代码的简化。于是代码就变成了这样(如果不使用retrolambda插件的话,要注意一下乱码的问题)。

        RealmAsyncTask task = realm
                .executeTransactionAsync(
                        realm1 -> Log.i("子线程", "执行异步操作!"),
                        () -> Log.i("主线程", "操作成功!"),
                        error -> Log.i("主线程", "操作失败!"));
  • 3.在界面销毁的时候,取消未完成的异步任务
    容我大胆的瞎说一下,这个跟退出界面后关闭子Thread和关闭动画(动画内部也是使用线程来实现的)的原理一样,都是为了防止内存泄漏。于是便在Activity或者Fragment的onDestory()方法中取消了未完成的异步任务。代码如下:
    @Override
    protected void onDestroy() {
        cancelTask(insertTask);
        cancelTask(updataTask);
        cancelTask(deleteTask);
        realm.close();
        super.onDestroy();
    }

    private void cancelTask(RealmAsyncTask task){
        if (task!=null&&!task.isCancelled()){
            task.cancel();
        }
    }

Realm的异步任务(查询)

  到了查询这就不能用上面的方法了,它有自己单独的方法。

  • 1.全查询
        RealmResults<Food> foods = realm.where(Food.class).findAllAsync();
        foods.addChangeListener(new RealmChangeListener<RealmResults<Food>>() {
            @Override
            public void onChange(RealmResults<Food> element) {
                //查询结束
            }
        });
  • 2.条件查询并返回第一个结果
        Food food = realm.where(Food.class).equalTo("name","A").findFirstAsync();
        food.addChangeListener(new RealmChangeListener<RealmModel>() {
            @Override
            public void onChange(RealmModel element) {
                //查询结束
            }
        });

例子中的增删改查操作

1、异步增

    /**
     * 添加数据
     */
    @Override
    public void insertDataToRealm(final Food food) {
        insertTask = realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {//执行异步操作
                Log.w("insertDataToRealm", "execute: ");
                Log.i("线程", Thread.currentThread().getName());
                realm.copyToRealm(food);
            }
        }, new Realm.Transaction.OnSuccess() {//操作成功
            @Override
            public void onSuccess() {
                Toast.makeText(AsyncActivity.this,"添加成功!",Toast.LENGTH_SHORT).show();
                Log.i("insertDataToRealm", "onSuccess: ");
                Log.i("线程", Thread.currentThread().getName());
                selectAllDataFromRealm();
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                Log.d("线程", Thread.currentThread().getName());
                Log.d("onError", error.getMessage());
            }
        });
    }

2、异步删

   /**
   * 删除数据
   * @param foodName
   */
    @Override
    public void deleteDataToRealm(final String foodName) {
        deleteTask = realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                //条件查询
                Food food = realm.where(Food.class).equalTo("name",foodName).findFirst();
                food.deleteFromRealm();//删除数据
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                Toast.makeText(AsyncActivity.this,"删除成功!",Toast.LENGTH_SHORT).show();
                selectAllDataFromRealm();
            }
        });
    }

3、异步改

    /**
     * 更新数据
     * @param foodName
     */
    @Override
    public void updataToRealm(final String foodName , final double price) {
        updataTask = realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                //条件查询
                Food food = realm.where(Food.class).equalTo("name",foodName).findFirst();
                food.setPrice(price);//更改价格
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                selectAllDataFromRealm();
                Toast.makeText(AsyncActivity.this,"修改成功!",Toast.LENGTH_SHORT).show();
            }
        });
    }

4、异步查

    /**
     * 异步全查询
     */
    private void selectAllDataFromRealm(){
        foods = realm.where(Food.class).findAllAsync();
        foods.addChangeListener(new RealmChangeListener<RealmResults<Food>>() {
            @Override
            public void onChange(RealmResults<Food> element) {
                Log.d("selectAllDataFromRealm", "查询到结果");
                Log.i("线程", Thread.currentThread().getName());
                List<Food> result = realm.copyFromRealm(foods);
                if (result.size() == 0){
                    Log.d("结果集", "没有数据");
                    return;
                }
                for (Food food : result){
                    Log.d("结果集", "------------------------------");
                    Log.w("类别", food.getType());
                    Log.w("名称", food.getName());
                    Log.w("价格", food.getPrice()+"");
                }
                if (foods.isLoaded()){
                    foods.removeChangeListeners();
                }
            }
        });
    }

使用RealmBaseAdapter

  使用起来需添加依赖:

compile 'io.realm:android-adapters:1.4.0'

  这里我用了RxJava1(RxJava)来结合Realm来执行异步查询,因为Realm支持RxJava。所以又添加了两个依赖:

compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
  • 1.创建适配器
/**
 * Author LYJ
 * Created on 2017/2/23.
 * Time 16:00
 */

public class TestAdapter extends RealmBaseAdapter<Food> implements ListAdapter {


    public TestAdapter(@NonNull Context context, @Nullable OrderedRealmCollection<Food> data) {
        super(context, data);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item, parent, false);
            viewHolder = new ViewHolder(convertView);
            viewHolder.name = ButterKnife.findById(convertView,R.id.name);
            viewHolder.price = ButterKnife.findById(convertView,R.id.price);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        Food food = adapterData.get(position);
        viewHolder.name.setText(food.getName());
        viewHolder.price.setText(String.valueOf(food.getPrice()));
        return convertView;
    }
    static class ViewHolder {
        @BindView(R.id.name)
        TextView name;
        @BindView(R.id.price)
        TextView price;
        ViewHolder(View view) {
            ButterKnife.bind(this, view);
        }
    }
}
  • 2.查询数据后加载数据
    /**
     * 加载数据
     */
    private void add() {
       realm.where(Food.class)
                .findAllAsync()
                .asObservable()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(foods -> {
                    listview.setAdapter(new TestAdapter(context,foods));
                });
    }

发布了41 篇原创文章 · 获赞 18 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/baidu_32377671/article/details/56678541
今日推荐