the problem that I am having is the following: For some reason onSuccess() is being call 2 minutes after all the code inside execute() is executed. Not sure why is taking that long.
CODE:
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Log.e("time-pre", Calendar.getInstance().getTime().toString());
RealmResults<TVRealm> tvRealms = realm.where(TVRealm.class)
.equalTo("favorite", true)findAll();
Log.e("time-post", Calendar.getInstance().getTime().toString());
}
}, new OnSuccess() {
#Override
public void onSuccess() {
Log.e("time-on-success", Calendar.getInstance().getTime().toString());
listener.onDataUpdate(tvList);
}
});
This is not happening on all devices, my understanding is that is only happening on devices that were using a really old realm db (like 0.84 on gradle) and after updating is causing this.
Does anyone has any clue about this issue?
Related
I have an ANR (Application is not responding) problem. I am trying to separate tasks into threads using AsyncTask, however it seems worse than before.
I am doing something wrong but I could not get where is the problem.
As you can see, the main thread takes 6M milliseconds which is not good I think.
To increase performance, I did those things in onCreate() methods of different activities:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
//TODO your background code
if(sPreferenceManager.getBoolean(Constants.SharedPreferences.UPDATE_REQUIRED))
{
log(Log.DEBUG,"mediaplayeractivity","UPDATE_REQUIRED");
mViewModel.getmInteractor().updateDatabaseAfterLogin();
}
}
});
AsyncTask.execute(new Runnable() {
#Override
public void run() {
//TODO your background code
initServices(savedInstanceState);
}
});
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Fabric.with(GomusApplication.this, new Crashlytics());
//TODO your background code
AndroidThreeTen.init(GomusApplication.this);
initPreferences();
sInstance = GomusApplication.this;
initRealm();
appComponent = DaggerAppComponent.builder()
.appModule(new
AppModule(GomusApplication.this)).build();
appComponent.inject(GomusApplication.this);
}
});
I separated tasks into AsyncTasks. However it made performance worse!
UPDATE:
I have changed my AsyncTasks like this but still I do not see any enhancement weirdly:
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
if(sPreferenceManager.getBoolean(Constants.SharedPreferences.UPDATE_REQUIRED))
{
log(Log.DEBUG,"mediaplayeractivity","UPDATE_REQUIRED");
mViewModel.getmInteractor().updateDatabaseAfterLogin();
}
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);
I also made some layout changes on constraint layouts like some fields were missing and I added them. I deleted some big images to increase the performance.
However, what I did made the performance worse. It was taking 3M milliseconds to run main thread but now it is 6M milliseconds.
I am so sorry, I have never tried to increase performance until now so I do not have enough knowledge. But I have made some research and people say that use AsyncTask.
Any help would be appreciated.
Thanks!
I am new to RxAndroid and tried the same with Room database. But the problem is that when inserting data into a database, then the progress bar that I am showing getting blocked and being sluggish. I referred this blog for the project
public void insertBillPayments(final CallBackParams params,
BillPaymentsOffline... payments) {
Completable.fromAction(() -> db.daoAccess().insertBillPayments(payments))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onComplete() {
params.getCallback().onOrderAdded(params);
}
#Override
public void onError(Throwable e) {
params.getCallback().onDataNotAvailable(params);
}
});
}
Please correct me if I am doing anything wrong.
This code seems fine, but I would recommend that you switch your observeOn and subscribeOn calls for clarity as subscribeOn applies to the stream and observeOn applies to the emitted values and functions applied after it.
http://reactivex.io/documentation/operators/observeon.html
My app implements a ChildEventListener to load the data into an ArrayList (approximately 7000 items).
During childAdded execution for each item, the interface freezes completely and can not be used.
Is there any way to run it in the background and that does not impair usability?
I've already tried using an AsyncTask and a Thread but the app freezes anyway. Thanks in advance.
class FBTask extends AsyncTas {
#Override
protected Boolean doInBackground(final Boolean... params){
int size = 7000; //aprox,
final ArrayList<Model> aux = new ArrayList<>();
Query db = FirebaseDatabase.getInstance().getReference()
.child("List").orderByChild("Double");
ChildEventListener cEL = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Model x = dataSnapshot.getValue(Model.class);
if(x.getT()!=null) {
aux.add(x)
Log.i("onChildAdded", x.getId() + " Added, pos: " + dX.size());
if(aux.size()>=size) {
data = aux;
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
db.addChildEventListener(cEL);
}
#Override
protected void onProgressUpdate(Boolean... values) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(DownAdapter result) {
if(result != null) {
DownActivity.downRecView.setAdapter(result);
}
}
#Override
protected void onCancelled() {
}
}
All network interaction and other work the Firebase client does already happens off the main thread. The only things that happens on the main thread are callbacks to your code, such onChildAdded(). This is done so you can update your UI from that code.
My guess is that calling dataSnapshot.getValue(Model.class) 7000 times is taking too much times, which is causing frames to be skipped. Do you really need 7000 models? I'd normally recommend to only retrieve data that you're going to show directly to the user, and 7000 models sounds like more than could reasonably fit on screen for most Android devices.
If you really must retrieve and decode that many items, you will need to use a AsyncTask or a background service. If you're having trouble making those work, share the minimal code that reproduces where you got stuck.
Every callbacks are handled by your Main Thread ( UI thread). Because you have large number of items (7000 items), there is array creation, copy of items from smaller to large array list is happening in runtime. This is causing ANR ( freeze your app). To avoid this, you can simply use new thread to add items in the array list. when you complete adding all items, do inter thread communication ( notify main thread) so that main thread does the further work. This is the exact solution. I had solved in the past the similar problem.
I made this post because I don't understand how transaction works using GreenDao and I would love to get some explanation/recent tutorial.
Despite of reading the Greendao github, I don't understand how the main activity works. For example:
...
Note note = new Note(null, noteText, comment, new Date(), NoteType.TEXT);
noteDao.insert(note)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Note>() {
#Override
public void call(Note note) {
Log.d("DaoExample", "Inserted new note, ID: " + note.getId());
updateNotes();
}
});
...
Do the observeOn method sends every insertion/update to one limited buffer? so, it will manage automatically the insertion to the real database when every operation was finished whithout problems?
Reading its API, we could see that they use rxTx and rxTxPlain for transactions (other way?), and finding out where are performed, I have to say I misunderstood everything. For example:
...
public void testConcurrentInsertDuringTx() throws InterruptedException {
...
Runnable runnable2 = new Runnable() {
#Override
public void run() {
dao.insertInTx(createEntity(null));
}
};
Runnable runnable3 = new Runnable() {
#Override
public void run() {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
}
};
...
// Builds the statement so it is ready immediately in the thread
dao.insert(createEntity(null));
doTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
latchThreadsDone.await();
assertEquals(7, dao.count());
}
...
I know this is an example, but I don't know the diferences of using the rx methods and the observeOn/subscribe ones
protected void doTx(final Runnable runnableInsideTx) {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
latchInsideTx.countDown();
// Give the concurrent thread time so it will try to acquire locks
try {
Thread.sleep(TIME_TO_WAIT_FOR_THREAD);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
runnableInsideTx.run();
}
});
}
I read some topics about transactions, but they are obsoletes or maybe, I didn't understand them correctly:
SQLite transaction behaviour using greendao
Android - Green Dao Multiple Transaction
Transactions in GreenDao
greenDAO 40 seconds to insert 600 records
https://groups.google.com/forum/#!topic/greendao/PXRwCRTbP6c
Someone could help me giving me some explanation/recent tutorial? Greendao have these methods as experimentals. Thanks in advance
I have a RecyclerView which displays items from a Realm database.
To do so I have implemented a RealmRecyclerViewAdapter based on the realm-android-adapters which gets an OrderedRealmCollection passed in.
For this I load the data with findAllAsync()
realm.where(Entry.class).findAllAsync()
When the user scrolls through the list he has the option to "favorite" some of the entries, which I have implemented with a normal OnClickListener on the "favorite" button.
Now I would love to update the "favorite" boolean of the entry whenever the user clicks the button. After the user clicked, a small animation is shown on the button.
For this I tried the following which sadly gives a wrong thread exception:
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
entry.setLiked(!entry.isLiked());
}
});
As an alternative I tried it with the normal executeTransaction which will work, but prevent the animation from being shown.
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
entry.setLiked(!entry.isLiked());
}
});
As an interesting addition this gives the following log:
Mixing asynchronous queries with local writes should be avoided. Realm will convert any async queries to synchronous in order to remain consistent. Use asynchronous writes instead.
Is there any possibility to update the item completely async without introducing lag or preventing the animation from being shown?
RealmRecyclerViewAdapter calls adapter.notifyDataSetChanged() when your Realm gets auto-updated, so the layout animation won't be called.
As for actually doing the change,
public class EntryViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.entry_favorite)
Button favButton;
public EntryViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
public void bind(Entry entry) {
final long entryId = entry.getId();
favButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Entry entry = realm.where(Entry.class)
.equalTo("id", id)
.findFirst();
if(entry != null) {
entry.deleteFromRealm();
}
}
});
}
});
}
}
Execute this on a background Thread. I recommend using classic Thread.class .Start animation outisde new Thread, and dismiss it through a callback on the UI Thread.
Realm realm = Realm.getInstance(..);
realm.beginTransaction();
YourClass yourClassInstance = realm.where(YourClass.class)
.equalTo(..)
.findFirst();
if(yourClassInstance != null){
yourClassInstance.setLiked(!yourClassInstance.getLiked());
}else{
yourClassInstance = realm.createObject(YourClass.class);
yourClassInstance.setLiked(whateverYouWant);
}
realm.commitTransaction();