So here's what happening: I'm using the runOnUiThread() method to change an Image View from another class when that class receives a message from another phone. I'm calling it by using mainclass.runOnUiThread(new Runnable...) and so on. It works the first time the application is run, but when I hit the back button to exit the application, and then launch the application again, the Image View no longer updates. The logs I took shows me that everything is fine and being run, but the Image View doesn't change. I don't get any errors and it doesn't crash when I run the application, it just doesn't update the Image View. Any idea what might be causing this?
Edit*: So this is what i'm actually using to change the imageView in a class that doesn't extend Activity
peerActivity.runOnUiThread(
new Runnable(){
#Override
public void run() {
Log.v("Thread#", "Thread is running");
Log.v("Thread#2", decodedImage.toString());
// TODO Auto-generated method stub
peerActivity.ivPhoto.setImageBitmap(decodedImage);
Log.v("Thread#3", "Past UI Change");
}
});
Where peerActivity holds the other class reference and ivPHoto is the Image View. What I think I need to do is find a way to kill that thread when the program closes (when I go into the program manager, it still has the Force Close button available). Is there any way to do this?
Edit2*: So I tried a bunch of different approaches to working on the UI Thread and they all give me the same result: The program works perfectly the first time its run but when I hit the back button and close it and the re-open it, the Image View no longer updates. If I force close the app, it works fine again until I close it and re-open it.
Try using View.post(...) instead.
I use new Handler(Looper.getMainLooper()).post(...);
You can even create this from a background thread.
It looks like your Runnable is closing over a reference to your activity. When you press back and then start your activity again, your old activity is destroyed and a new instance is created. Your background thread continues to make changes to the original activity, which no longer exists, therefore making changes to its views has no effect.
You need to either stop the updating thread when the actiivty is paused or stopped as appropriate and restart it when the activty is resumed or started (again, as appropriate) and make sure that you are always updating the activty that is actually visible.
Related
Hello our application works perfect but when our users move the app to background, after a while coming back to app its been crashing.
For example i open the app then change three pages then move the app to background. after open from background 30 minutes its crash because its try to load activity when i resumed
Another applications do this from mainactivity, for example: instagram,twitter vs vs.
another applications not to try load resume activity, they are trying to main activity
how can i start my app from mainactivity when user come back to app from background ?
well, the better way would be to identify the null objects and reassign or repopulate them in the onResume() method so that the user can actually return to what they were doing.
if you can't or it's not an option, then try this code in every activity that you do not want to return to.
override fun onTrimMemory(level: Int) {
this.finishAffinity()
}
this code closes the active activity as soon as the app goes into background so when returned, the app is forced to start from the launcher activity.
Although I am not convinced that this is the best approach. there might be something better.
I perform a network call in which I
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
and then I pass the result to an io.reactivex.function.Consumer, which attempts to animate a view.
These animations worked when I was loading the data locally and synchronously, but broke when I introduced this server call.
Now when I animate the views, it does not change any of the properties at all, but instead just instantly calls the animation complete listener.
I verified that I'm on the main thread with Looper.getMainLooper().isCurrentThread()
Yet the only way I've been able to get the animation working again is to wrap it in AndroidSchedulers.mainThread().scheduleDirect(() -> {})
Which as shown by this piece of code shouldn't actually change anything
final Thread before = Thread.currentThread();
AndroidSchedulers.mainThread().scheduleDirect(() -> {
boolean nothingChanged = before == Thread.currentThread();
//nothingChanged is true
});
Why do I have to reschedule the animation back onto the thread it is already on in order to get it to work?
Edit: RxJava is not involved, something even weirder is going on.
I cut out RxJava and the issue is reproducing even though I put the animation code in onNavigationItemSelected(), which is called by android when the user clicks something, so its definitely in the right thread.
My animation looks like this.
alertBanner.clearAnimation();
alertBanner.animate()
.alpha(0)
.translationY(alertBanner.getHeight())
.setDuration(500)
.setListener(new AnimatorListenerBuilder().setOnAnimationEnd(animator -> {
alertBanner.setVisibility(GONE);
}))
.start();
AnimatorListenerBuilder is just a utility class that wraps AnimatorListener and lets you only define the callbacks that you want. It works for all the other animations in my app and hasn't been changed in months.
I figured it out. It was a race condition.
When the user clicked the button, two things happened:
A new fragment was created, and an animation was started.
However, the fragment had a callback, onAttach() that would, among other things, call .clearAnimation() on the view I was trying to animate.
By rescheduling the animation back onto the main thread, I was making sure that it happened after the fragment callback.
I solved it by getting rid of the callback from the fragment, and putting that logic in the same place as the logic that starts the animation, allowing me to control the execution order.
I have this wierd situation that i can't understand.
I developed an application on android studio, on the first activity i start a second activity, on that second activity i created a SurfaceView child class that extends surfaceView and implemment Runnable and draw on the canvas inside run(), when i exit the thread i call onRestart() to start the canvas thread again.
all good so far, i open the thread, draw some images in a loop, exit the thread loop, restart.
the problem is that after 20 times of restarting, the application crash with no logical reason.
what do you think the problem can be? how to check it and fix it?
this function is the thread work inside the surfaceView child class (of the activity)
#Override
public void run() {
while (!_susspendThread) {
// draw images
}
onRestart();
}
this function is on the parent activity class
protected void onRestart() {
// make some changes, nothing critical to the question
// examp. count++;
surface_view.StartThreadWork();
}
another thing i must say although i dont belive it's related to the problem is that onCreate i read some internal files.
thanks for any help.
You have a memory leak, and this could be from many things. A good place to begin, is to use the onDestroy() methods of your Activities to cleanup any resources you have generated (like the internal files you are creating in your onCreate method).
Also, there are tons of tools for tracking memory usage, in AndroidStudio (AS) there is a "Memory" tab in the "Android" view. Also, you can run the "Monitor" tool (available from the command-line, or within AS to get ton's of details on what type of resource you are leaking.
I have some floating bugs in my app, which unable to reproduce clearly. I suspect them from inproper work of my SaveInstanceState|restoreInstanceState mechanism, so I need to check case, when activity is being stopped when goes to background, and recreating after I press back button from spawned activity. Is there a way to force android stop and destroy activity which went to background? It should remain on activity stack, so I cannot just finish it.
Just enable the developer option "don't keep activities" (or whatever its called). This won't remove the activity from the stack, but will actually call onStop() and onDestroy() whenever the user leaves the activity and opens another. When the user presses BACK, Android will create a new instance of the activity, and call onCreate() and onRestoreInstanceState()` as expected.
Looks like it's a copy of this and this questions. Override onPause() method and call method finish() in it.
I have an activity that sets a custom created view "onCreated" and a Thread is started, this thread cycles every 23ms and "invalidates" this view so it's onDraw is called almost always.
This view continues in screen until a user clicks on it (onTouchEvent) and view does some proceses and when ready a public flag ins enabled so the activity "knows" when the view was activated and has made it's proceses, in this moment the activity should change it's view to another one custom created, the problem is that because the flag checking is done in the run method of the thread the activity sends a "CallFromWrongThreadException", this is because as far as I understand the "changing" is in another thread (not UI).
I have set the runOnUiThread to overpass this and the srceen goes completly black.
Also I have tried to set the activity to a framelayout in which I add both views at begging and the thread changes visibiliity of the views, no success at all.
All view manipulation must happen on the UI thread. There are a few ways to do this. One is to use AsyncTask to perform your background work, as it has means to run code on the UI thread after the background work has completed.
Another option is to post the code you want to run through the view itself, like this:
mMyView.post(new Runnable() {
public void run() {
mMyView.doSomething();
}
});
This method would work well for toggling the visibility of an existing view.
This is a good overview of these methods: http://android-developers.blogspot.com/2009/05/painless-threading.html