Execute transaction method using Realm continues to loop on each run android

☆樱花仙子☆ 提交于 2019-12-13 03:05:37

问题


In my app I am using Realm DB to store all the data in local database. I have some initial mock data which I want to show at the starting of the app. Previously I implemented begintransaction method. But after reading the documentation I have implented execute tranasction method. Beacuse this method is updating my new data easily. Now the problem is, whenever I click the option to show the recyclerview, the data is looping each time. for example I have 3 data. If I go back to previous page and again go to this recyclerview page, it becomes double, next time it becomes tripple and so on. I want to show only the updated data into the view. Like if I add 4th data iwant to show this to recyclerview. How can I stop looping on each run in my app.

Here is my code

Person Page

public class InitialData implements Realm.Transaction {
@Override
public void execute(Realm realm) {
    List<PersoneModel> person = new ArrayList<>();
    PersonModel model = new PersonModel();
    model.setId(1 + System.currentTimeMillis());
    model.setName("Name1");
    model.setCompany("Comapny1");
    model.setTitle("Title1");
    person.add(model);

    model = new PersonModel();
    model.setId(2 + System.currentTimeMillis());
    model.setName("Name2");
    model.setCompany("Company2");
    model.setTitle("Title2");
    person.add(model);

    model = new PersonModel();
    model.setId(2 + System.currentTimeMillis());
    model.setName("Name2");
    model.setCompany("Company2");
    model.setTitle("Title2");
    person.add(model);

    model = new PersonModel();
    model.setId(3 + System.currentTimeMillis());
    model.setName("Name3");
    model.setCompany("Comapny3");
    model.setTitle("Title3");
    person.add(model);

    for (PersonModel realmModel : colleague) {
        realm.insertOrUpdate(realmModel);
    }
}

@Override
public boolean equals(Object obj) {
    return obj != null && obj instanceof InitialData;
}

@Override
public int hashCode() {
    return InitialData.class.hashCode();
}

}

News Page Initial Data

    public class InitialDataNews implements Realm.Transaction {
    @Override
    public void execute(Realm realm) {
    List<NewsModel> newsItem = new ArrayList<>();
    NewsModel model = new NewsModel();

    model.setId(1+System.currentTimeMillis());
    model.setImage(R.drawable.image1);
    model.setTitle("title1");
    model.setDate("12.07.2017");
    model.setDetail("deascription");
    newsItem.add(model);


    model = new NewsModel();
    model.setId(3+System.currentTimeMillis());
    model.setImage(R.drawable.image3);
    model.setTitle("title2");
    model.setDate("05.05.2017");
    model.setDetail("description");
    newsItem.add(model);

    model = new NewsModel();
    model.setId(4+System.currentTimeMillis());
    model.setImage(R.drawable.image4);
    model.setTitle("title3");
    model.setDate("13.04.2017");
    model.setDetail("description3");
    newsItem.add(model);


    .....


    for (NewsModel realmModel : newsItem) {
    realm.insertOrUpdate(realmModel);
    }
}
@Override
public boolean equals(Object obj) {
    return obj != null && obj instanceof InitialData;
}

@Override
public int hashCode() {
    return InitialData.class.hashCode();
  }

}

Base Application

 @Override
public void onCreate() {
    super.onCreate();
    // The Realm file will be located in Context.getFilesDir() with name "default.realm"
    //Here we setup the realm configuration.
    //Setting a default configuration in custom Application class, will ensure that it is available in the rest of the code.
    Realm.init(this);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
        .deleteRealmIfMigrationNeeded()
        .initialData(CompositeInitialData.of(new InitialDataNews(), new InitialData()).build());
    Realm.setDefaultConfiguration(realmConfiguration);
  }

Add change Listener

public class PersonPage extends AppCompatActivity implements PersonAdapter.PersonListListener{

private RecyclerView recyclerView;
private PersonAdapter adapter;
private Realm PersonRealm;
private RealmResults<PersoneModel> personResult;

private RealmChangeListener realmListener;


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


    personRealm = Realm.getDefaultInstance();
    recyclerView = (RecyclerView) findViewById(R.id.colleagues_recycler);

    realmListener=new RealmChangeListener() {
        @Override
        public void onChange(Object o) {
            showAllPersons();
        }};
    colleagueRealm.addChangeListener(realmListener);

    setUpRecycler();
    }

 private void showAllPersons() {
    realmResult = personRealm.where(PersonModel.class).findAllAsync();
    setAdapter(realmResult);
    adapter.notifyDataSetChanged();
}

private void setAdapter(RealmResults<PersonModel> results) {

    adapter = new PersonAdapter(this, personRealm.where(PersonModel.class).findAllSortedAsync("id"),this);
    recyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

回答1:


That's because in onCreate(), you run basicCRUD(personRealm); which adds new person models

            PersonModel model = new PersonModel();
            model.setId(1 + System.currentTimeMillis());
            model.setName("Name1");
            model.setCompany("Comapny1");
            model.setTitle("Title1");
            person.add(model);

As you set id as 1 + System.currentTimeMillis(), it will be a new object with a different primary key, and it gets inserted. If it were just 1, 2 and so on then it'd update them as the same object.

Thankfully, Realm provides the initialData(Realm.Transaction) method on the RealmConfiguration.Builder() which allows you to create the initial data for the database only when the database is first created, or if the data is deleted after deleteRealmIfMigrationNeeded().

public class InitialData implements Realm.Transaction {
    @Override
    public void execute(Realm realm) {
        List<PersonModel> person = new ArrayList<>();
        PersonModel model = new PersonModel();
        model.setId(1 + System.currentTimeMillis());
        model.setName("Name1");
        model.setCompany("Comapny1");
        model.setTitle("Title1");
        person.add(model);

        model = new PersonModel();
        model.setId(2 + System.currentTimeMillis());
        model.setName("Name2");
        model.setCompany("Company2");
        model.setTitle("Title2");
        person.add(model);

        model = new PersonModel();
        model.setId(3 + System.currentTimeMillis());
        model.setName("Name3");
        model.setCompany("Company23");
        model.setTitle("Title3");
        person.add(model);

        model = new PersonModel();
        model.setId(4 + System.currentTimeMillis());
        model.setName("Name4");
        model.setCompany("Comapny4");
        model.setTitle("Title4");
        person.add(model);

        for (PersonModel realmModel : person) {
            realm.insertOrUpdate(realmModel);
        }
    }

    @Override
    public boolean equals(Object object) {
        return object != null && object instanceof InitialData;
    }

    @Override
    public int hashCode() {
        return InitialData.class.hashCode();
    }
}

And

Realm.init(this);
Realm.setDefaultConfiguration(new RealmConfiguration.Builder()
                                    .deleteRealmIfMigrationNeeded()
                                    .initialData(new InitialData())
                                    .build());

EDIT:

To provide multiple "initial datas" in only one "initial data" (as you provide 1 transaction), you can rely on the composite design pattern to provide multiple initial datas in just one initial data, like so

public final class InitialDataPersons implements Realm.Transaction {
    @Override
    public void execute(Realm realm) {
        List<PersonModel> person = new ArrayList<>();
        PersonModel model = new PersonModel();
        model.setId(1 + System.currentTimeMillis());
        model.setName("Name1");
        model.setCompany("Comapny1");
        model.setTitle("Title1");
        person.add(model);

        model = new PersonModel();
        model.setId(2 + System.currentTimeMillis());
        model.setName("Name2");
        model.setCompany("Company2");
        model.setTitle("Title2");
        person.add(model);

        model = new PersonModel();
        model.setId(3 + System.currentTimeMillis());
        model.setName("Name3");
        model.setCompany("Company23");
        model.setTitle("Title3");
        person.add(model);

        model = new PersonModel();
        model.setId(4 + System.currentTimeMillis());
        model.setName("Name4");
        model.setCompany("Comapny4");
        model.setTitle("Title4");
        person.add(model);

        for (PersonModel realmModel : person) {
            realm.insertOrUpdate(realmModel);
        }
    }

    @Override
    public boolean equals(Object object) {
        return object != null && object instanceof InitialDataPersons;
    }

    @Override
    public int hashCode() {
        return InitialDataPersons.class.hashCode();
    }
}

and

public final class InitialDataNews implements Realm.Transaction {
    @Override
    public void execute(Realm realm) {
        List<NewsModel> newsItem = new ArrayList<>();
        NewsModel model = new NewsModel();

        model.setId(1+System.currentTimeMillis());
        model.setImage(R.drawable.image1);
        model.setTitle("title1");
        model.setDate("12.07.2017");
        model.setDetail("deascription");
        newsItem.add(model);

        model = new NewsModel();
        model.setId(3+System.currentTimeMillis());
        model.setImage(R.drawable.image3);
        model.setTitle("title2");
        model.setDate("05.05.2017");
        model.setDetail("description");
        newsItem.add(model);

        model = new NewsModel();
        model.setId(4+System.currentTimeMillis());
        model.setImage(R.drawable.image4);
        model.setTitle("title3");
        model.setDate("13.04.2017");
        model.setDetail("description3");
        newsItem.add(model);

        .....

        for (NewsModel realmModel : newsItem) {
            realm.insertOrUpdate(realmModel);
        }
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null && obj instanceof InitialDataNews;
    }

    @Override
    public int hashCode() {
        return InitialDataNews.class.hashCode();
    }
}

and

public final class CompositeInitialData implements Realm.Transaction {
    private final Realm.Transaction[] transactions;

    private CompositeInitialData(Realm.Transaction... transactions) { // `of` is prettier
        this.transactions = transactions;
    }

    public static CompositeInitialData of(Realm.Transaction... transactions) {
        return new CompositeInitialData(transactions);
    }

    @Override
    public void execute(Realm realm) {
        for(Realm.Transaction transaction : transactions) {
            transaction.execute(realm);
        }
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null && obj instanceof CompositeInitialData; // you might want autogenerated equals instead
    }

    @Override
    public int hashCode() {
        return CompositeInitialData.class.hashCode(); // you might want autogenerated hashCode instead
    }
}

This way you can provide

Realm.init(this);
Realm.setDefaultConfiguration(new RealmConfiguration.Builder()
             .deleteIfMigrationNeeded()
             .initialData(CompositeInitialData.of(new InitialDataNews(), new InitialDataPersons()))
             .build());


来源:https://stackoverflow.com/questions/45592132/execute-transaction-method-using-realm-continues-to-loop-on-each-run-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!