【问题标题】:Android Realm Arraylist and simple POJOAndroid Realm Arraylist 和简单的 POJO
【发布时间】:2017-05-22 20:29:28
【问题描述】:

我从外部数据库(使用改造)检索了许多(6600 行)对象,这些对象看起来和我的 POJO 类一起工作。之后,我尝试将其放入 Realm 对象中,但速度非常慢。我怀疑这个缓慢的动作是因为我开始逐行提交事务。也许有人知道如何在一次提交中将完整的数组列表放入领域对象? 我的主要:

private class AsyncTaskRetro extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {

            PlacesAPI.Factory.getInstance().getPlaces().enqueue(new Callback<Places>() {

                @Override
                public void onResponse(Call<Places> call, Response<Places> response) {
                    for (int i = 0; i < response.body().getPosts().size(); i++) {
                        RowModel rowModel = new RowModel(response.body().getPosts().get(i).getNazwa(),
                                Double.parseDouble(response.body().getPosts().get(i).getSzer()),
                                Double.parseDouble(response.body().getPosts().get(i).getDlug()));
                        rowModels.add(rowModel);
                    }
                    String oldName;
                    oldName = rowModels.get(0).getName();
                    shopsNames.add(rowModels.get(0).getName());


                    mRealm.beginTransaction();
                    RowModel rowModelRealm = mRealm.createObject(RowModel.class);
                    mRealm.commitTransaction();
                    for (int j = 0; j < rowModels.size(); j++) {
                        mRealm.beginTransaction();
                        rowModelRealm.setName(rowModels.get(j).getName());
                        rowModelRealm.setLattitude(rowModels.get(j).getLattitude());
                        rowModelRealm.setLongitude(rowModels.get(j).getLongitude());
                        mRealm.commitTransaction();

                        if (rowModels.get(j).getName().equals(oldName)) {
                            continue;
                        }
                        oldName = rowModels.get(j).getName();
                        shopsNames.add(rowModels.get(j).getName());
                    }



     //sortowanie 

listy z nazwami sklepow
                    Collections.sort(shopsNames);

                adapter = new ShopsAdapter(MainActivity.this, shopsNames);

                recyclerView.setAdapter(adapter);


            }

            @Override
            public void onFailure(Call<Places> call, Throwable t) {

            }
        });

        return null;
    }
}

和 POJO:

public class RowModel extends RealmObject {

    @Required
    private String name;
    @Required
    private Double lattitude, longitude;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getLattitude() {
        return lattitude;
    }

    public void setLattitude(Double lattitude) {
        this.lattitude = lattitude;
    }

    public Double getLongitude() {
        return longitude;
    }

    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }

    public RowModel(String name, Double lattitude, Double longitude) {
        this.name = name;
        this.lattitude = lattitude;
        this.longitude = longitude;
    }

    public RowModel() {
    }
}

【问题讨论】:

    标签: java android arraylist realm


    【解决方案1】:

    1.) 你使用的是 Realm 0.82.2,这个版本有一些怪癖,这就是为什么我推荐的下一个稳定版本是 0.87.5;但实际上最新稳定版本(目前)是 3.1.4。

    您可能应该切换到不到 2 岁的版本?

    2.) 您正在运行 AsyncTask,但您在其中使用了 enqueue

    getPlaces().enqueue(new Callback<Places>() {    
          @Override
          public void onResponse(Call<Places> call, Response<Places> response) {
    

    这意味着 Retrofit 回调将在 UI 线程上执行。

    然后,您执行同步事务,因此您在 UI 线程上写入 Realm,这很糟糕。

    3.) 您尝试手动对下载的元素进行排序,然后也手动在适配器中显示它们,如果您使用的是 Realm,这没有意义,因为 Realm 允许按特定字段对元素进行排序。此外,shopsNames 绝对不是 RealmResults,这意味着您甚至没有监听对 DB 所做的更改。

    ShopsAdapter 应该是RealmBaseAdapter


    所以代码应该更像这样

    private class AsyncTaskRetro
            extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected Void doInBackground(Void... voids) {
            try(Realm r = Realm.getDefaultInstance()) {
                Response<Place> response = PlacesAPI.Factory.getInstance().getPlaces().execute();
                Place place = response.body();
                List<Post> posts = place.getPosts();
                r.executeTransaction((realm) -> {
                    for(Post post : posts) {
                        RowModel rowModel = new RowModel(post.getNazwa(),
                                Double.parseDouble(post.getSzer()),
                                Double.parseDouble(post.getDlug()));
                        rowModels.add(rowModel);
                    }
                    String oldName;
                    oldName = rowModels.get(0).getName();
                    shopsNames.add(rowModels.get(0).getName());
    
                    RowModel rowModelRealm = realm.createObject(RowModel.class);
                    for(RowModel rowModel : rowModels) {
                        rowModelRealm.setName(rowModel.getName());
                        rowModelRealm.setLattitude(rowModel.getLattitude());
                        rowModelRealm.setLongitude(rowModel.getLongitude());
    
                        if(rowModel.getName().equals(oldName)) {
                            continue;
                        }
                        oldName = rowModel.getName();
                        shopsNames.add(rowModel.getName());
                    }
                });
                // no need to manually sort if you use RealmBaseAdapter with findAllSorted()
            }
            return null;
        }
    }
    

    【讨论】:

    • 现在我使用最新版本 3.2.1,先将实例更改为 init,然后再使用 Realm.getDefaultinstance();一切都运行得又快又好。谢谢你们!
    • 3.2.1 中有一个已知错误,如果您使用 Proguard,则需要添加 -keepnames public class * extends io.realm.RealmObject,否则也可以使用
    【解决方案2】:

    Realm 对象具有以下方法: insert(Iterable&lt;E&gt; objects) 这应该可以让您一次复制所有 RowModel 对象

    【讨论】:

    • 看起来没问题,但是后来怎么把它放到我的 POJO 模型 Arraylist 中呢?
    • 为什么不直接使用RealmListRealmResults 对象?两者都是集合,但如果你真的需要数组列表,那么你可以从RealmList 对象创建一个。假设rowModels 是您的数组列表,只需执行rowModels = new ArrayList&lt;&gt;(*your realm collection*)
    • 好的,但问题是将此对象传递给另一个活动。当我这样做时,像 RowModel rowModelRealm = mRealm.createObject(RowModel.class);我可以通过以下方式在第二个活动中简单地访问它:Realm realm = Realm.getInstance(this); RealmResults rowModels = realm.where(RowModel.class).equalTo("name", "Tesco").findAll();
    • Realm.getInstance(this); 表示您最多仍在使用 Realm 0.82.2。如果您使用的是 2 年前的旧版本,人们将无法为您提供帮助,您至少应该切换到 3.1.4
    猜你喜欢
    • 2016-05-08
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    相关资源
    最近更新 更多