RecyclerView not clearing (notifyDataSetChanged not working) - android

I've had a look everywhere on here and nothing is related to my problem. Basically I've implemented a feature which changes the reading direction of my app (1 or -1) now I can get it to initially change direction and it works really well but when I get it to change back (using the same code but changing the direction) it just doesn't update. Just seems like notifyDataSetChanged(); doesn't want to work the second time...?
My code is as as follows:
private void flip() {
if (!isFlipped) {
mData.getItems().removeAll(mData.getItems());
mAdapter.notifyDataSetChanged();
isFlipped = true;
loadData(false, -1);
closeMenu();
} else {
mData.getItems().removeAll(mData.getItems());
mAdapter.notifyDataSetChanged();
isFlipped = false;
loadData(false, 1);
closeMenu();
}
}
What am I doing wrong?
Again, thanks in advance :)

Implement a public method in your RecyclerView code, e.g:
public void clearAll(){
mData.clear();
this.notifyDataSetChanged();
}
And then call that function from your activity (or Fragment):
private void flip() {
if (!isFlipped) {
mAdapter.clearAll();
isFlipped = true;
loadData(false, -1);
closeMenu();
} else {
mAdapter.clearAll();
isFlipped = false;
loadData(false, 1);
closeMenu();
}
}

Related

What triggers and what happens on onPageDataChanged?

In a project I am working on, there is a class that uses Modelcallbacks. One of its callbacks is onPageDataChanged.
I have searched on the net but cannot find what triggers and what happens on the callback function.
Can someone please explain it to me? Thanks in advance!
#Override
public void onPageDataChanged(Page changedPage) {
ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
for (Page page : mWizardModel.getCurrentPageSequence()) {
page.getReviewItems(reviewItems);
}
Collections.sort(reviewItems, new Comparator<ReviewItem>() {
#Override
public int compare(ReviewItem a, ReviewItem b) {
return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0;
}
});
mCurrentReviewItems = reviewItems;
if (mReviewAdapter != null) {
mReviewAdapter.notifyDataSetInvalidated();
}
}

How to check for tap in monogame?

I want to check that Rectangle was tapped. This mehod does the job and it works almost how I want:
private bool CheckRectangleTouch(Rectangle target)
{
var touchCollection = TouchPanel.GetState();
if (touchCollection.Count > 0)
{
foreach (var touch in touchCollection)
{
if (target.Contains(touch.Position))
{
return true;
}
}
}
return false;
}
Problem I have is that after I've tapped rectangle it keeps returning true until I release it (it can register 10-30 times for one tap) and I want it to return true just once - for the first touch.
I've tried this (replace code inside foreach):
var isFirstTouch = !touch.TryGetPreviousLocation(out _);
if (target.Contains(touch.Position) && isFirstTouch)
{
return true;
}
And this (bad one, I don't really want it to register after release):
if (target.Contains(touch.Position) && touch.State == TouchLocationState.Released)
{
return true;
}
But nothing is does it. Either logic is not consistent or doesn't work at all.
So how do I check for tap?
Update: this works but it's very hacky, has delay and gives me random phantom taps:
try
{
var tap = TouchPanel.ReadGesture(); // falls each time when no input
return tap.GestureType == GestureType.Tap && target.Contains(tap.Position);
}
catch { }
return false;
Here's what I ended up doing:
I have singleton to hold my game state (many different props updated as needed). I added to it:
public TouchCollection TouchCollection { get; set; }
Prop to hold TouchPanel.GetState result. I fill it in Games Update method once per frame, as #craftworkgames suggested:
State.TouchCollection = TouchPanel.GetState();
Also I added this prop to my game state:
public bool TouchActive { get; set; }
And this is the method to check for rectangle tap. It returns true only for the first contact in tap:
private bool CheckRectangleTap(Rectangle target)
{
if (State.TouchCollection.Count == 0)
{ // if no input
return State.TouchActive = false;
}
var targetTouched = false;
foreach (var touch in State.TouchCollection)
{
if (target.Contains(touch.Position))
{
targetTouched = true;
}
}
if (targetTouched && !State.TouchActive)
{ // if target is touched and it's first contact
return State.TouchActive = true;
}
return false;
}
It doesn't seem ideal but it works for my case.

Strange behavior - App suddenly producing ANR

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.

How to disable call inside onChecked change conditionally?

I have toggle(Switch) buttons inside my fragment.After coming on the fragment I am reading BLE values and setting the toggle buttons.
#Override
public void sosStatus(boolean sosvalue, BluetoothGattCharacteristic sosCharac) {
if (sosvalue) {
byte[] charValue = sosCharac.getValue();
String valueOfCharInstring = StringUtils.byteToHex(charValue[0]);
Log.d("+++++SosStatus",""+sosCharac.getUuid().toString() + " " + valueOfCharInstring);
if (sosCharac.getUuid().toString().equalsIgnoreCase(BLEConstants._BUTTON_CHARACTERISTIC)) {
if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.EnableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Enabled");
// touchButton.setChecked(true);
// tvTouchButtonAction.setText("Enabled");
} else if (valueOfCharInstring.equalsIgnoreCase(BLEConstants.DisableCharacInString)) {
setButtonStatus(touchButton,R.id.switch_btn_device_touch,"Disabled");
// touchButton.setChecked(false);
// tvTouchButtonAction.setText("Disabled");
}
}
if (characList.size() > 0) {
gattclientCallBack.readCharacteristicMain(UUID.fromString(characList.remove(characList.size() - 1)));
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
}
} else {
useOnCheckedChangeMethod = true;
showProgress(false);
HandleCharacListData(true,false,"");
}
}
Now since Switch widget is used, what is happening is that when I read the values programatically for first time, it works fine.but when I toggle the button with touch, onCheckChanged is repeatedly getting called as if I set some value, it keeps on calling itself in infinite loop. This is my oncheckchanged code.
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
try {
if (useOnCheckedChangeMethod) {
switch (compoundButton.getId()) {
case R.id.switch_btn_device_touch:
touchButton.setOnCheckedChangeListener(null);
//showProgress(true);
HandleCharacListData(true,false,"");
HandleCharacListData(false,false,BLEConstants.TOUCH_BUTTON_CHARACTERISTIC);
if(characList!=null && characList.size()>0) {
if(b) {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.DisableCharac);
}
else {
gattclientCallBack.writeCharacteristic(characList.remove(characList.size() - 1), BLEConstants.EnableCharac);
}
}
Log.d("Touch++++", "+++");
break;
}
So it continuously keep on toggling as on and off due to the check if(b). :)
what can I do to ensure that the onCheckChange methos only gets called once after the value is set ?
Things that I have also tried
1) Use onClick listener and disable call in oncheckchanged and enable on click.
2) Use onTouch
Thank you :)
That interesting, because inside of setChecked() it actually checks to see if it's in the middle of broadcasting and returns...
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
The only solution I know of is un-registering the callback before calling setChecked() and register the callback again after your call returns. This works because the callback isn't called asynchronously but instead, called immediately inside of setChecked().
Hey I got my answer in the link below to a question framed little differently . Thanks to this guy :)
onCheckedChanged called automatically

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