How to update SurfaceView from another Thread? - android

I have a thread where I will get some Bitmap one by one. Then whenever I get a new Bitmap I need to update my SurfaceView which in the main thread. How can I do this?

Here is some pseudo code
new Thread() {
public void run() {
while (bitmapIncoming()) {
Bitmap bitmap = getNextBitmapAfterLongOperation();
mActivityReference.runOnUiThread(new Runnable() {
public void run() {
mActivityReference.updateSurfaceView(bitmap);
}
});
}
}
}.start();

In the thread, make a public interface which defines a function which is called every time a bitmap is retrieved(from the internet i assume) like:
public interface ImageRetrievedListener{
public void onImageReceived(Bitmap bitmap);
}
Implement this method inside your Activity where you are using the Surface View and in the onImageReceived callback, add the Bitmap received into the array of Bitmaps which the SurfaceView uses. Should work, if you still have any problems, do let me know.
//EDIT
Not sure if this is the best possible solution for this problem, but i'd solve it this way.

Related

Why does Picasso running in a background thread block onActivityResult?

We are working on a share mode for photos in an app, and one of the share options is to load an overlay for the image online. If the user shares the photo before the overlay finishes loading we are sending an intent with the unmodified image to share to other apps with startActivityForResult, and then in onActivityResult we are returning the user to the normal photo view from the share view.
The issue we are running into is that when the user returns from sharing the photo, onActivityResult isn't called until the background thread that is loading the overlay finishes. Is there a reason that a background thread would suddenly start to block the UI thread?
Here is the code we are using inside of our overlay view class which extends ImageView to manage this:
private void asyncLoadImage() {
new Thread(new Runnable() {
#Override
public void run() {
loadImage();
}
}).start();
}
private void loadImage() {
try {
overlayBitmap = Picasso.with(getContext()).load(url).get();
if (overlayBitmap != null) {
displayBitmap();
} else {
displayError();
}
} catch (IOException ignored) {
displayError();
}
}
We have tried using Picasso targets as well instead of creating our own thread and we run into the exact same issue, the only solution so far has been to use Ion asynchronously (however, using Ion synchronously or trying to cancel the Ion request futures before we call startActivityForResult result in the same UI thread blocking issues). This feels like a huge hack since we are using Picasso everywhere else in the app.
Is there a reason why these background tasks would be blocking the UI thread when returning to the activity?
Looking at your code you are creating a new thread when you don't need to. Picasso has a configurable executor method for threading.
I had an issue when loading over 100+ images using picasso and it would lock up and block the UI Thread on me but this was due to it creating a new Thread every time I called picasso to get an image. I solved this by doing a little research and found that within picasso there is a configurable executor method.
This is my ImageHandler class implementation
public class ImageHandler {
private static Picasso instance;
public static Picasso getSharedInstance(Context context)
{
if(instance == null)
{
instance = new Picasso.Builder(context).executor(Executors.newSingleThreadExecutor()).memoryCache(Cache.NONE).indicatorsEnabled(true).build();
return instance;
}
else
{
return instance;
}
}
}
I don't know that this is your issue, but it would be worth a try if you haven't implemented it yet.
Here is the way I use it to load images
ImageHandler.getSharedInstance(getApplicationContext()).load(imString).skipMemoryCache().resize(width, height).into(image, new Callback() {
#Override
public void onSuccess() {
layout.setVisibility(View.VISIBLE);
}
#Override
public void onError() {
}
});

Android:getting following error "Only the original thread that created a view hierarchy can touch its views."

Here is my code for Progress Dialog in Android and i am getting following error:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. I saw all previous post related to this error but i could not correct this error.
// Waiting screen
pleaseWaitdialog = ProgressDialog.show(PhoneBookListView.this, "Loading", "Please wait...", true);
new Thread(new Runnable() {
#Override
public void run()
{
Looper.prepare();
// do the thing that takes a long time
LoadContactFromPhoneAndSim();
PhoneBookListView.this.runOnUiThread(new Runnable() {
#Override
public void run()
{
pleaseWaitdialog.dismiss();
}
});
}
}).start();
Any help will be appreciate
Thanks.
I suggest you use an AsyncTask, as they make this sort of thing easier. In general, you want to do complex stuff on a background thread, and only update the UI from the UI thread.
public class PhonebookLoader extends AsyncTask<Void,Void,Void> {
protected Void doInBackground(Void ... params) {
LoadContactFromPhoneAndSim();
return void;
}
protected void onPostExecute(Void param) {
pleaseWaitdialog.dismiss();
}
}
To start it with this class, you just call this:
new PhonebookLoader.execute();
And you can do all kinds of things with this, like publish your progress so the user knows how far they have progressed, update the UI thread after you are done loading, etc. AsyncTask is your friend, use it.
Looking at this, I suspect that PhonebookLoader is probably both loading the data and putting it on the UI. Separating these two tasks will make your app much more responsive and easier to maintain.

Threading on Android

I have the following void:
public void load() {
//loading big picture from the Internet
}
And i want it to run in a new Thread.
I can call this procedure like this:
new Thread(new Runnable() {
public void run() {
load();
}
}).start();
or it would be better to modify this void:
public void load() {
new Thread(new Runnable() {
public void run() {
//loading big picture from the Internet
}
}).start();
}
and simply call it:
load();
Or there is no different?
Functionally, they are identical. There are designed details that might make you consider the first way over the other.
You may want the first option if you had a lot of different threads that didn't their own individual things but also called load(). In that case, you already had created the thread, so if they called load() you wouldn't want/need to create another.
The second option is very convenient. You can simply call load() wherever you want. If, in the future, the load() method changes to a point where it's not blocking, then you can change it and no further code changes would be needed.
Alternatively, consider using AsyncTask for this as previously suggested. It was specifically built for exactly what you're trying to do.

How can I run my code after Activity is made visible?

I have an Activity with 3 spinners. These spinners get their data from a web-service by a method that takes about 1 minute to be completed.
I want to load the Activity first and after it is made visible, call that web-service method and load data. I have tested the following codes separately but none of them solved my problem. In these samples application goes into a black screen and when the web-service operation completed, it is made visible.
#Override
protected void onCreate() {
//.........
final Runnable r = new Runnable()
{
public void run()
{
loadMyData();
}
};
Utilities.performOnBackgroundThread(r);
}
#Override
protected void onResume() {
new Thread() {
#Override
public void run() {
loadMyData();
}
}.start();
super.onResume();
}
#Override
protected void onStart() {
if (comesFromOnCreateMethod)
{
final Runnable r = new Runnable()
{
public void run()
{
loadMyData();
}
};
Utilities.performOnBackgroundThread(r);
}
comesFromOnCreateMethod = false;
super.onStart();
}
#Override
protected void onResume() {
if (comesFromOnCreateMethod)
{
final Runnable r = new Runnable()
{
public void run()
{
loadMyData();
}
};
Utilities.performOnBackgroundThread(r);
}
comesFromOnCreateMethod = false;
}
If you are getting a black screen, then I would assume your code is being run on the UI thread and not on the background, causing the UI to hang until the work is completed.
One of the best solutions to doing background work is an AsyncTask. Using this, you can call it in your onCreate() method, and when its done, it will post a callback to the UI thread for you in which you can display you data.
If you want this method to run everytime this Activity displays, then call it in onResume(). Otherwise, call it in onCreate().
In your onCreate, make the async tasks as the others have advised. Make sure you generate the content for the app first and then call the asyncTasks. You can control your spinners from the callback.
First of all, you might want to increase your accept rate, 39% is pretty low.
Anyway, you might want to check AsyncTask, it should do the thing. http://developer.android.com/reference/android/os/AsyncTask.html
Typically, you will want to initialize in onPreExecute, do the networking in the doInBackGround, and set the result to the UI thread on the OnPostExecute. Hope this will help.
Use AssynchTask() and you should call super.onResume() or any lifecycle method in respective life cycle method first then other specific method you want to do....

problem loading images asynchronously

I have an application that uses images from web a a source. for my application I'm first downloading images in seperate thread and only if image exists on disk I show on the list. Downloader is a seperate thread, but I'm very new using threads and now something else is confusing me. My images are not shown unless I refresh the view, that is my list. Now I needed to show my images so I wrote this in my custom view :
private Runnable LoaderTask=new Runnable(){
public void run() {
if(cellIcon!=null){
if(iconCache.get(cellIcon)!=null){
icon.setImageBitmap(iconCache.get(cellIcon));
mHandler.postDelayed(this, 200);
}
}
}
};
private class ImageThread extends Thread{
#Override
public void run() {
// mHandler.removeCallbacks(LoaderTask);
mHandler.postDelayed(LoaderTask, 100);
}
}
And I trigger my thread like this
ImageThread thread=new ImageThread();
thread.start();
the handler is instantiated in the beginning of the class. But when I do this n othing happen until I refresh my views. I tried (Activity).runOnUIThread inside one of my threads I got stackoverflow error. How do I solve that or are there any other advices.you can give me? Thanks
Use AsyncTask. In onPostExecute() method just call a method from the activity and refresh the UI. The onPostExecute() is called when the thread is done.
http://developer.android.com/resources/articles/painless-threading.html
P.S. To call an activity's method just use Interface.
Have a look at this:
http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

Categories

Resources