Strange behavior - App suddenly producing ANR - android

I know it sounds strange/ridiculous, but I am having this issue
Update#2
I am sharing the code that is indicated by #EpicPandaForce.
SyncService.onNetworkSuccess
public void onNetworkCallSuccess(Response response) {
List<TransactionHistory> historyList = (List<TransactionHistory>) response.body();
if(historyList != null && historyList.size() > 0) {
TransactionHistory max = Collections.max(historyList, new Comparator<TransactionHistory>() {
#Override
public int compare(TransactionHistory o1, TransactionHistory o2) {
return o1.getUpdatedAt().compareTo(o2.getUpdatedAt());
}
});
if(max != null) {
session.putStringForKey(Session.timeStamp, String.valueOf(max.getUpdatedAt()));
}
for(TransactionHistory history : historyList) {
String id;
if(history.getTo().equals(history.getFrom()) ||
history.getFrom().equals(session.getStringForKey(Session.fpIdKey)))
id = history.getTo();
else id = history.getFrom();
LatestTransactionResponse latestTransactionResponse = new LatestTransactionResponse();
DateTransactionResponse dateTransactionResponse = new DateTransactionResponse(DateUtility.getDateFromEpoch(history.getEpoch()));
dateTransactionResponse.addTransaction(history);
latestTransactionResponse.setArchived(history.isArchived());
latestTransactionResponse.addTransaction(history);
latestTransactionResponse.setId(id);
dateTransactionResponse.setId(id);
LatestTransactionRepository.getInstance().addLatestTransaction(realm,
latestTransactionResponse);
ContactTransactionRepository.getInstance().addNewTransaction(realm, dateTransactionResponse, id);
}
try {
Activity temp = MyFirebaseMessagingService.getRunningActivity();
if(temp != null) {
if(temp instanceof MainActivity) {
((MainActivity) temp).refreshLatestTransactions();
} else if(temp instanceof TransactionDetailActivity) {
((TransactionDetailActivity) temp).refreshOnMainThread();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
addNewTransaction
public void addNewTransaction(Realm realm, final DateTransactionResponse response, final String id) {
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
List<TransactionHistory> tempHistoryList;
DateTransactionResponse temp = realm
.where(DateTransactionResponse.class)
.equalTo("id", id)
.equalTo("date", response.getDate())
.findFirst();
if(temp == null)
realm.insertOrUpdate(response);
else {
tempHistoryList = temp.getTransactions();
for(TransactionHistory history : response.getTransactions()) {
boolean found = false;
for(int i=0; i < tempHistoryList.size(); i++) {
if (history.getId().equals(tempHistoryList.get(i).getId())) {
if(history.getStatus().equals(tempHistoryList.get(i).getStatus())) {
found = true;
break;
} else {
tempHistoryList.get(i).setStatus(history.getStatus());
}
}
}
if(!found)
tempHistoryList.add(history);
}
//realm.insertOrUpdate(temp);
realm.copyToRealm(temp);
//DateTransactionResponse transactionResponse = temp;
//temp.deleteFromRealm();
//realm.insertOrUpdate(temp);
}
}
});
//removeDuplicateTransactions(realm);
}
removeDuplicateTransaction
private void removeDuplicateTransactions(Realm realm) {
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmQuery<DateTransactionResponse> query = realm.where(DateTransactionResponse.class);
RealmResults<DateTransactionResponse> results = query.findAll();
List<DateTransactionResponse> transactions = new ArrayList<>(results);
for(DateTransactionResponse response : transactions) {
List<TransactionHistory> historyList = response.getTransactions();
Set<TransactionHistory> historySet = new LinkedHashSet<>(historyList);
RealmList<TransactionHistory> histories = new RealmList<>();
histories.addAll(new ArrayList<>(historySet));
response.setTransactions(histories);
realm.copyToRealm(response);
}
}
});
}
Update#1
There are 3 tabs with RecyclerViews on my main screen. Below are the implementation of Adapter for all three.
I have been developing an App for quite a time. It has been working just fine and I occasionally work to improve its performance. It is still under development. Some days ago, I cut-out the branch and done nothing notable (just one or two bug fixes) and started testing it and OOPS it started giving ANR's. I revert back to previous branch and very strangely it started giving me the same result. I have removed all changes and tried, still the same result. I am not sure what's happening. I tried to study traces.txt, but couldn't find waiting to lock as suggested in this SO answer.
I have also difficulty reading traces, couldn't find the culprit. Here is the traces.txt file.
I am using Realm as Database in my application and couldn't find a way to perform operations on Realm on other thread. I tried to find any other culprit in code, but all is till the same as before which was working perfectly fine.
Hierarchy
Here is the App Hierarchy.
Login screen is shown and user enters PIN. Then comes the main screen. Main screen contains 4 tabs, just like WhatsApp i.e first tab is camera and rest contains RecyclerViews in which data is being populated from Realm. ANR is only happening here. Keeping in mind that it was literally perfect some days ago until I took branch out and fixed some bugs, which were not even related to the main screen.
Any help or direction is highly appreciated.

Related

how to avoid duplicate retrofit 2 calls when a condition is met using viewpager.addOnPageChangeListener

Hello amazing programmers of stack overflow, I'm trying to make a network request when a condition is met on viewpager.AddOnPageChangeListner using retrofit2, and showing progress dialog while it fetches the data, the problem is when swiping across the screen sometimes, the same network request is triggered twice resulting in duplicate data and sometimes it just works fine, what changes can i make to avoid duplicate network request.
mPager.addOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (imageUrls.size() - 1 == position & !nextCursor.equals("") & Util.isNetworkAvailable()) {
if (mResources != null){
mResources.clear();
}
// retrofit network request method
fetchImages(category, nextCursor);
}
if ((imageUrls.size() - 1 == position) & (Util.isNetworkAvailable() == false)) {
Toast.makeText(MainActivity.this, "No Internet " + imageUrls.size(), Toast.LENGTH_SHORT).show();
}
}
Below is the retrofit request method declaration
private void fetchImages(final String mCategory, final String mNextCursor) {
dialog.show();
call = ApiUtils.getImageService().getImageResource(mCategory, mNextCursor);
call.enqueue(new Callback<ImageResponse>() {
#Override
public void onResponse(Call<ImageResponse> call, Response<ImageResponse> response) {
imageResponse = response.body();
if (imageResponse.getResources() != null) {
mResources = imageResponse.getResources();
for (int i = 0; i < mResources.size(); i++) {
String imageUrl = mResources.get(i).getUrl();
String imageName = mResources.get(i).getPublicId();
Log.i("retrofitImageUrl",imageName);
imageUrls.add(imageUrl);
imageNames.add(imageName);
}
if (imageResponse.getNextCursor() != null) {
nextCursor = imageResponse.getNextCursor();
} else {
nextCursor = "";
}
imageInfo = ImageInfo.getInstance();
imageInfo.setImageUrls(imageUrls);
imageInfo.setPublicImageId(imageNames);
imageInfo.setNextcursor(nextCursor);
imageInfo.setCategoryType(mCategory);
String jSon = gson.toJson(imageInfo);
editor.putString("imageInfo",jSon);
editor.commit();
if (mPagerAdapter == null) {
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(), mContext);
mPager.setAdapter(mPagerAdapter);
mPagerAdapter.notifyDataSetChanged();
}else {
mPagerAdapter.notifyDataSetChanged();
}
}else {
Toast.makeText(MainActivity.this,"No valid data was returned, please try again",Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
}
#Override
public void onFailure(Call<ImageResponse> call, Throwable t) {
dialog.dismiss();
Toast.makeText(MainActivity.this, "error:something went wrong", Toast.LENGTH_SHORT).show();
}
});
}
I was able to fix the issue by using Async task and change retrofit network request type to synchronous by adding following if condition
if (urls.size() - 1 == position & !nextCursor.equals("") & Util.isNetworkAvailable()) {
mResources.clear();
if ((imageDownloadAsyncTask.getStatus() != Status.RUNNING)&(imageDownloadAsyncTask.getStatus() != Status.PENDING)) {
asyncTask(category);
}
}
I'd really like to use retrofit async call rather than separate async task but how do i avoid duplicate calls using retrofit ? I couldn't find call.pending or call.running method in retrofit. Any help will be highly appreciated !!
In you case I think you need to implement some kind image cache system. Basically, if you already have downloaded an image you don't make a new call to download again the image. Plus you will need some kind flag to know if you are currently downloading a image or not.
I would suggest you to use Picasso, Glide or ImageDownloader that already provide all of this.

Realm add item to RealmList that is added to RealmObject

I need to solve putting data to a realm database like this:
I have an object called obtained_code;
I have a realmList of Obtained codes in an object called Offer;
I download obtained codes separately, and by their offer id assign them to the lists of each object. The problem is that I can't add them because when I check the size, it's always 0.
Here is the code:
ObtainedCodes codes = response.body();
for (ObtainedCode c : codes.getObtainedCodes()) {
Offer offer = RealmController.with(SplashActivity.this).getOffer(c.getOffer_id());
if (offer != null) {
Log.d("Size", "Offer not null");
realm1.beginTransaction();
RealmList<ObtainedCode> list = offer.getObtained_codes();
if (!list) { // if the 'list' is managed, all items in it is also managed
RealmList<ObtainedCode> managedImageList = new RealmList<>();
for (ObtainedCode item : list) {
if (item) {
managedImageList.add(item);
} else {
managedImageList.add(realm1.copyToRealm(item));
}
}
list = managedImageList;
}
offer.setObtained_codes(obtainedCodes);
Log.d("Size", String.valueOf(offer.getObtained_codes().size()));
realm1.copyToRealmOrUpdate(offer);
realm1.commitTransaction();
}
offer = RealmController.with(SplashActivity.this).getOffer(c.getOffer_id());
Log.d("Size", String.valueOf(offer.getObtained_codes().size()));
}
1.) the Ravi Tamada tutorial on InfoHive is a terrible mess, please refer to my remake of that example instead.
If you managed to start using 0.82.1 because Ravi Tamada claimed that a 4 years old version is "stable", well I know that it's not. Use 1.2.0 instead (or the latest version which is 3.4.1)
And if you see a RealmController.with(), run, because it ignores thread-confinement. The moment you try to access it from a background thread, it'll crash.
On background threads, you'd need to do
#Override
public void run() {
try(Realm realm = Realm.getDefaultInstance()) {
repository.whatever(realm); // pass Realm instance to database methods
} // auto-close
// end of thread
}
2.) you are executing writes on the UI thread, that is bad, from UI thread you should use realm.executeTransactionAsync(), but in your case you should actually execute the Retrofit call on a background thread using Ęxecutors.newSingleThreadedPool() and call it with call.execute() instead of call.enqueue().
3.) You should write to Realm on the background thread, and on the UI thread you should use RealmChangeListener to listen to writes.
4.) your code doesn't work because you're setting an unmanaged list to a managed RealmObject.
You should modify the existing RealmList inside the RealmObject, and add only managed objects to it.
Executor executor = Executors.newSingleThreadExecutor(); // field variable
// ...
void someMethod() {
executor.execute(new Runnable() {
#Override
public void run() {
Response<ObtainedCodes> response = retrofitService.getObtainedCodes().execute(); // run on current thread
ObtainedCodes codes = response.body();
if(codes == null) return;
try(Realm r = Realm.getDefaultInstance()) {
r.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
for(ObtainedCode obtainedCode : codes.getObtainedCodes()) {
Offer offer = realmRepository.getOffer(realm, obtainedCode.getOfferId());
if(offer == null) {
offer = realm.createObject(Offer.class, obtainedCode.getOfferId());
// map properties to offer if possible
}
RealmList<ObtainedCode> offerCodes = offer.getObtainedCodes();
ObtainedCode managedObtainedCode = realm.where(ObtainedCode.class).equalTo("obtainedCodeId", obtainedCode.getId()).findFirst();
if(managedObtainedCode == null) {
managedObtainedCode = realm.createObject(ObtainedCode.class, obtainedCode.getId());
// map properties from obtained code to managed obtained code
}
if(!offerCodes.contains(managedObtainedCode)) {
offerCodes.add(managedObtainedCode);
}
}
}
});
}
}
});
}

realm and IntentService

I have filled realm database. Everything works well.
The application has a button, pressing it starts IntentService. It is very simple for test
code here
public class HNotificationService extends IntentService {
public HNotificationService() {
super("HNotificationService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("HNotificationService", "onHandleIntent");
Realm realm = Realm.getDefaultInstance();
RealmResults<HPartner> mResPartner = realm.where(HPartner.class).findAll();
final HPartner hPartner = mResPartner.get(0);
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
hPartner.setName("test");
}
});
realm.close();
}
}
After this code is executed, the database becomes empty! I do not see any errors in the log.
Note. Cleaning the database occurs only when I want to record something.
I will be glad of any help
EDIT1
Inside application class. I use this code
RealmConfiguration config = new RealmConfiguration.Builder(this).build();
Realm.setDefaultConfiguration(config);
EDIT2
yes you are right database is not deleted!
Log.e("HNotificationService", "empty"); - It is never called, and it's good
Realm realm = Realm.getDefaultInstance();
RealmResults<HPartner> mResPartner = realm.where(HPartner.class).findAll();
if (mResPartner.size() > 0) {
Log.e("HNotificationService", "don't empty!");
}
final HPartner hPartner = mResPartner.get(0);
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
hPartner.setName("test");
}
});
mResPartner = realm.where(HPartner.class).findAll();
if (mResPartner.size() == 0) {
Log.e("HNotificationService", "empty");
}
realm.removeAllChangeListeners();
realm.close();
Another reason. When I go to a different screen I'm calling code
mResPartners = Realm.getDefaultInstance().where(HPartner.class).findAllAsync();
mResPartners.removeChangeListeners();
mResPartners.addChangeListener(mPartnersListener);
And mPartnersListener is never called. It is very strange.
if don't run IntentService. mPartnersListener always called
EDIT 3
mPartnersListener = new RealmChangeListener<RealmResults<HPartner>>() {
#Override
public void onChange(RealmResults<HPartner> realmResult) {
mResPartners.removeChangeListeners();
mClusterManager.clearItems();
mGoogleMap.clear();
if (realmResult != null && realmResult.size() > 0) {
mListPartners = realmResult;
getLoaderManager().restartLoader(LMarkerIcons.ID_LOADER, null, FrAroundMeMap.this);
}
}
};
I think, I find out the problem !You remove allChangelisteners in your IntentService, after logs in this part.
mResPartner = realm.where(HPartner.class).findAll();
if (mResPartner.size() == 0) {
Log.e("HNotificationService", "empty");
}
realm.removeAllChangeListeners();
realm.close();
and then you do new query, add NEW changeListener and want get notifications from him, but after send notification, listener removed by code above.
adding changelistener to async fetched realmResult - correct, should work fine!
So remove this block in IntentSevice
realm.removeAllChangeListeners();
Also your listener looks very strange, see coments in your onChange
mPartnersListener = new RealmChangeListener<RealmResults<HPartner>>() {
#Override
public void onChange(RealmResults<HPartner> realmResult) {
// here U remove listener BEFORE do your stuff and
// onChange will never called again
// If U`ll put log here U find out, that listener was called
// simple delete block -> mResPartners.removeChangeListeners();
mResPartners.removeChangeListeners();
mClusterManager.clearItems();
mGoogleMap.clear();
if (realmResult != null && realmResult.size() > 0) {
mListPartners = realmResult;
getLoaderManager().restartLoader(LMarkerIcons.ID_LOADER, null, FrAroundMeMap.this);
}
}
};
Something that bugs me in this code is that you should obtain the latest version of the realm object inside the transaction
#Override
protected void onHandleIntent(Intent intent) {
Log.d("HNotificationService", "onHandleIntent");
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<HPartner> mResPartner = realm.where(HPartner.class).findAll();
final HPartner hPartner = mResPartner.get(0);
hPartner.setName("test");
}
});
realm.close();
}
Other than that, I would try replacing the async() query with the sync version.
mResPartners = Realm.getDefaultInstance().where(HPartner.class).findAll();
Also worth noting the fact that Realm.getDefaultInstance().where( this construct means you'll never be able to close the Realm on the UI thread.
EDIT: Are you sure
mResPartners.removeChangeListeners();
Doesn't cause any problems in your change listener?

Using popBackStack() in Android does not update android-listview with Firebase data

At the beginning of the chat app user see a list off groups (listview group) available and the user have the possibility to create a new group or click on some off the available groups and then start to write messages (listview messages). The functions CreateNewMessage and CreateNewGroup pushes information to firebase correctly
Above scenarios works finne problems arise when user navigates backwards (popBackStack()) from listview with messages to GroupFragment, here should user be presented a list off available groups but the listview is empty. The ReadGroupData() function is not reading the already created groups from firebase and inserts them in the group listview. How to make this happen?
GroupFragment:
public void ReadGroupData() {
Firebase firebaserootRef = new Firebase("https://000.firebaseio.com");
firebaserootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.getValue() != null) {
Group newGroup = new Group((String)snapshot.child("name").getValue(),
(String) snapshot.child("id").getValue());
if(!groupKeyValues.contains(newGroup.GetId())) {
groupKeyValues.add(newGroup.GetId());
AddToLstViewGroup(newGroup);
System.out.println("Read group data from firebase and
inserted in listView");
}
}
}
});
}
public void AddToLstViewGroup(Group newGroup) {
groupNameList.add(newGroup);
if(groupAdapter == null) {
groupAdapter = new GroupAdapter(getActivity(), groupNameList);
}
if (lstViewGroup == null) {
lstViewGroup = (ListView) getView().
findViewById(R.id.listView_group);
}
lstViewGroup.setOnItemClickListener(onItemClickListener);
lstViewGroup.setOnItemLongClickListener(onItemLongClickListener);
groupAdapter.notifyDataSetChanged();
lstViewGroup.setAdapter(groupAdapter);
}
ChatFragment:
public void ReadChatMessages(Firebase firebaseRootRef) {
firebaseRootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String s) {
if (snapshot.child(GetGroupId()).child("messages").
getChildren() != null) {
for (DataSnapshot c :
snapshot.child(GetGroupId()).child("messages").getChildren()) {
String key = c.getKey();
Message newMessage = new Message();
newMessage.SetFrom((String) c.child("from").getValue());
newMessage.SetMsg((String)
c.child("message").getValue());
newMessage.SetTime((String) c.child("time").getValue());
newMessage.SetId((String) c.child("id").getValue());
if ((!msgKeyValues.contains(key)) ||
newMessage.GetFrom() != "") {
msgKeyValues.add(key);
AddToLstViewChat(newMessage);
//Automatic scrolls to last line in listView.
lstViewChat.setSelection(chatAdapter.getCount() -1);
}
}
}
}
public void AddToLstViewChat(Message newMessage) {
chatMsgList.add(newMessage);
if (chatAdapter == null) {
chatAdapter = new ChatAdapter(getActivity(), chatMsgList);
}
if(IsMsgFromMe(newMessage)) {
lstViewChat = (ListView)
getView().findViewById(R.id.listView_chat_message_me);
} else {
lstViewChat =
(ListView)getView().findViewById(R.id.listView_chat_message_others);
}
chatAdapter.notifyDataSetChanged();
lstViewChat.setAdapter(chatAdapter);
}
ChatActivity:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
finish();
}
}
For all the code click on the link: "http://pastebin.com/97nR68Rm"
SOLUTION!
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for lstViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view, To clarifying:
Deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced with:
ListView lstViewGroup=(ListView)getView().findViewById(R.id.listView_group);
Kato thank you for you patience and help. I have now found a solution for the problem. I'm calling ReadGroupData() and ReadChatMessages() at the end (before return) in my onCreateView methods. As Kato pointed out onCreate() is not getting called on popBackStack()
In my AddToLStViewGroup the if statement for listViewGroup is deleted so now it always sets the listView otherwise it will throw an exception for not finding the correct view.
To clarify:
I deleted this line:
if (lstViewGroup == null) {
lstViewGroup = (ListView)getView().findViewById(R.id.listView_group);
}
And replaced it with:
ListView lstViewGroup =(ListView)getView().findViewById(R.id.listView_group);
(The original asker posted the answer as part of the question. I'm copying it here as a matter of housekeeping.)

Roman Nurik's Wizard pager - how to access collected data?

I am trying to make a wizard using Roman Nurik's library (https://plus.google.com/113735310430199015092/posts/6cVymZvn3f4).
I am having trouble accessing the collected data from the Review Fragment.
I made mCurrentReviewItems public in ReviewFragment and then I tried it like this
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mPager.getCurrentItem() == mCurrentPageSequence.size()) {
ReviewFragment reviewFragment = (ReviewFragment) mPagerAdapter.getItem(mPager.getCurrentItem());
for (ReviewItem item : reviewFragment.mCurrentReviewItems)
Log.d(MainActivity.TAG, "Item: " + item.getDisplayValue());
}
} else {
if (mEditingAfterReview) {
mPager.setCurrentItem(mPagerAdapter.getCount() - 1);
} else {
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
}
}
}
});
However its always null.
Inside if (mPager.getCurrentItem() == mCurrentPageSequence.size()) { }
For single page variable:
String data = mWizardModel.findByKey("Sandwich:Bread").getData().getString(Page.SIMPLE_DATA_KEY);
For customized page:
String data =
mWizardModel.findByKey(THE_KEY).getData().getString(CustomerInfoPage.YOUR_DATA_KEY);
If you want to assign the data back to the wizard, put this at the end of onCreate in FragmentActivity:
Bundle data = new Bundle();
if (!TextUtils.isEmpty(DATA_STRING)) {
data.putString(Page.SIMPLE_DATA_KEY, DATA_STRING);
mWizardModel.findByKey("Sandwich:Bread"").resetData(data);
}
The key "Sandwich:Bread" is from the example, change whatever suit you. Never try the multi one, I think it is more or less the same.
Sorry for big delay, but I think that someone will found this info useful. I found a way to get all ReviewItems since you can have a lot of branches and you won't be able to use the first answer.
I'm pretty sure, that your mPagerAdapter::getItem code looked like in example (so it just returned new fragment, instead of returning current pager fragment). You have to use instantiateItem to get reference on your ReviewFragment.
Object o = mPager.getAdapter().instantiateItem(mPager, mPager.getCurrentItem());
if(o instanceof ReviewFragment) {
List<ReviewItem> items = ((ReviewFragment) o).getCurrentReviewItems();
if(items != null) {
Log.v(TAG, "Items are: " + items.toString());
}
}
This is my code #Anton_Shkurenko
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mPager.getCurrentItem() == mCurrentPageSequence.size()) {
Object o = mPager.getAdapter().instantiateItem(mPager, mPager.getCurrentItem());
if(o instanceof ReviewFragment) {
List<ReviewItem> items = ((ReviewFragment) o).getCurrentReviewItems();
if(items != null) {
Log.v(TAG, "Items are: " + items.toString());
}
}
}
}
});
The best solution is to include this library in your project as module, and implement your own method for getting review items in ReviewFragment.
public List<ReviewItem> getReviewItems() {
return mCurrentReviewItems;
}
I am not sure why developer did not add that. It's the most important thing in project. Choose items and DO something with them.
Anyone still looking for a solution for this issue you can use following code
ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
for (Page page : mWizardModel.getCurrentPageSequence()) {
page.getReviewItems(reviewItems);
}

Categories

Resources