0

I am developing cv using RecyclerView how can I save retrofit api response into realm and use offline on android?

below my Adapter where I have implemented CV introduction and image

public class IntroductionAdapter extends RecyclerView.Adapter {

private List<Introduction> introductionList;
Context context;     // changes

public IntroductionAdapter(Context context, List<Introduction> introductionList) {   // changes
    this.context = context;    // changes(here you can see context)
    this.introductionList = introductionList;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(context)
            .inflate(R.layout.introduction_list, parent, false);  // change

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
    final Introduction introduction = introductionList.get(position);


    if (introduction.getImage() != null) {

        Glide.with(holder.imageView).load(introduction.getImage()).into(holder.imageView);
    }


    holder.introduction.setText(introduction.getIntroduction());

}

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

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView introduction, about;
    public CircularImageView imageView;

    public MyViewHolder(View view) {
        super(view);


        introduction = (TextView) view.findViewById(R.id.introduction);
        about = (TextView) view.findViewById(R.id.about);
        imageView = (CircularImageView) view.findViewById(R.id.circularImageView);

    }
}

}

below IntroductionItem.java where I have implemented Realm in offline mode

public class IntroductionItem extends AppCompatActivity { public RealmList introductionList;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.introduction);

    RecyclerView recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    //TODO move this initialization to App extends Application

    RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().build();

    final Realm realm = Realm.getInstance(realmConfiguration);

    KitabInterface kitabInterface = ApiClient.getApiService();
    Call<KitabSawti> call = kitabInterface.getIntroduction();
    call.enqueue(new Callback<KitabSawti>() {
        @Override
        public void onResponse(Call<KitabSawti> call, Response<KitabSawti> response) {

            introductionList = response.body().getIntroduction();
            recyclerView.setAdapter(new IntroductionAdapter(IntroductionItem.this, introductionList));

            realm.beginTransaction();
            for (int i = 0; i < introductionList.size(); i++) {

                Introduction introduction = realm.createObject(Introduction.class);
                introduction.setImage(introductionList.get(i).getImage());
                introduction.setIntroduction(introductionList.get(i).getIntroduction());

            }
            realm.commitTransaction();


        }

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

            List<Introduction> list = realm.where(Introduction.class).findAll();
            if (list != null) {

                recyclerView.setAdapter(new IntroductionAdapter(IntroductionItem.this, list));

            }

        }

    });


}

}

below Introduction.java class public class Introduction extends RealmObject {

@SerializedName("image")
@Expose
private String image;
@SerializedName("introduction")
@Expose
private String introduction;

public String getImage() {
    return image;
}

public void setImage(String image) {
    this.image = image;
}

public String getIntroduction() {
    return introduction;
}

public void setIntroduction(String introduction) {
    this.introduction = introduction;
}

}

2 Answers2

0

I believe every time when you get a success response, you are only adding the same result to the realm, which explains why you're getting repeating items when in offline mode.

If you only want to overwrite existing results, you could try:

    @Override
    public void onResponse(Call<KitabSawti> call, Response<KitabSawti> response) {

        introductionList = response.body().getIntroduction();
        recyclerView.setAdapter(new IntroductionAdapter(IntroductionItem.this, introductionList));

        realm.beginTransaction();
        realm.delete(Introduction.class); // Remove older values first
        realm.commitTransaction();

        realm.beginTransaction();
        for (int i = 0; i < introductionList.size(); i++) {
            Introduction introduction = realm.createObject(Introduction.class);
            introduction.setImage(introductionList.get(i).getImage());
            introduction.setIntroduction(introductionList.get(i).getIntroduction());

        }
        realm.commitTransaction();
    }

Or realm.clear(Introduction.class) if you're using older Realm. And for this solution to work, you may need to clear your app data, or simply uninstall and install again.

Otherwise you may need to find another workaround so that your Introduction class support unique property.

Aaron
  • 3,764
  • 2
  • 8
  • 25
  • app stopped working at all it is not showing any data when it is offline – Snowdinjon Edgarjon Nov 04 '18 at 07:23
  • Oh my bad, maybe try `realm.beginTransaction(); realm.delete(Introduction.class); realm.commitTransaction();` in a separate block, then begin transaction again adding the new results. – Aaron Nov 04 '18 at 07:28
  • If your Introduction class has primary key, then you could just `realm.copyToRealmOrUpdate(introductionList)` instead. – Aaron Nov 04 '18 at 07:30
  • Aaron can you update your edit app not working in offline mode – Snowdinjon Edgarjon Nov 04 '18 at 07:31
  • @SnowdinjonEdgarjon yeah updated, see if it works, good luck! – Aaron Nov 04 '18 at 07:37
  • And can I assume you have cleared the app data, or uninstalled the app, and have the app connected to the internet the first time? – Aaron Nov 04 '18 at 07:41
  • it should work withount internet connection first right – Snowdinjon Edgarjon Nov 04 '18 at 07:49
  • Sorry I'm lost, yes it should work, but I'd expect an empty list, how else do you get data on the first time when you're offline? Unless you have offline data in your resource folder, otherwise I can't see how but do correct me if I'm wrong. – Aaron Nov 04 '18 at 08:02
  • I think it is working first I am running app online mode and then offline when I click overview tab it is working I have implemented for this app bottom navigation bar for other items when test offline it is not working – Snowdinjon Edgarjon Nov 04 '18 at 08:07
  • Sorry I'm completely lost now, you should probably refine your question. I only thought your items kept growing and repeating. – Aaron Nov 04 '18 at 08:17
  • reedit my question I want to implement saved retrofit response to realm and used when app gets offline – Snowdinjon Edgarjon Nov 04 '18 at 08:20
  • @Aoron are u here – Snowdinjon Edgarjon Nov 04 '18 at 08:36
  • What you have already done for saving the result to realm is correct, but the only problem with that is every time you get successful result, you are appending the result with the existing ones, which explains why you're list was growing and repeating the first place. I think what you want is to update the list instead of adding more to the list, hope I am right about this. So in that case the quickest way to do so is to delete your Introduction table every time you get a new list. – Aaron Nov 04 '18 at 08:53
  • how can I achieve that – Snowdinjon Edgarjon Nov 04 '18 at 09:29
  • By the way can you also post your Introduction code please? – Aaron Nov 04 '18 at 09:31
  • Aaron, You are so helpful I will post it soon – Snowdinjon Edgarjon Nov 04 '18 at 09:37
  • I have added Introduction.java class please check it – Snowdinjon Edgarjon Nov 04 '18 at 09:42
  • So you do not have a primary key in your Introduction class, then you can only do it this way: whenever you're online and the response returns successfully, delete your existing introduction list from realm, then add the new ones. The answer I posted should do the trick or feel free to tweak around, realm should load your introduction list when it's offline, but on one condition: it must get the data online first. If you think that's wrong, unfortunately I can't think of any other solution. – Aaron Nov 04 '18 at 09:54
  • I will accept this answer I did not get any answer as well – Snowdinjon Edgarjon Nov 04 '18 at 10:11
  • Sorry if I couldn't answer you fully, but I hope my explanation is sufficient enough to get you somewhere, good luck! – Aaron Nov 04 '18 at 10:15
  • maybe you can help with this one https://stackoverflow.com/questions/53141925/java-lang-runtimeexception-java-lang-runtimeexception-com-android-builder-dexi – Snowdinjon Edgarjon Nov 04 '18 at 14:38
0

Not sure about this. But you can try adding this two things in your adapter:

@Override
public long getItemId(int position) {
    return position;
}

And change your constructor like this:

public IntroductionAdapter(Context context, List<Introduction> introductionList) {   
    this.context = context;    
    this.introductionList = introductionList;
    setHasStableIds(true);

}