My code mainly decodes a series of bitmap objects to be displayed in an ImageView later. To get more control over the duration to display each image. So i implemented the code in a Runnable. Here is a snippet of that runnable.
final File file[]=dir.listFiles();
iv.postDelayed(
new Runnable() {
#Override
public void run() {
i++;
Bitmap bitmap = decodeFile(file[i]);
iv.setImageBitmap(bitmap);
iv.postDelayed(this, 5000);
}
}, 5000);
However, I don't seem to have a good control over the looping here. I am not able to use a for loop since "i" cant be assigned to zero in this case. This code works as long as the "file[i]" has a File reference to it. As soon as it displays all the images once, the app just force closes do to arrayindexoutofbounds exception. I just want to continue the loop infinitely. Any pointers?
Here decodeFile() calls another function to rescale the size of the bitmap.
I'm not really sure what you are doing, but why not use a while loop instead? Something like while (true) { } would cause the infinite loop.
sense you want to do some work that might take a while and you want do repeat it, try looking at an android component called service and send it the images by intent.
http://developer.android.com/guide/topics/fundamentals/services.html
probably an IntentService would be fine, and help alot
http://developer.android.com/reference/android/app/IntentService.html
I suggest an AsyncTask
File means a file array is given the task to be processed in the background.
Bitmap means you call publishProgress with your bitmap, you fetch it on the UI thread in onProgressUpdate
Void means you simply stop once it is done.
The good thing here is that the decoding is done on a background thread, but the iv.setBitmap is still called on the UI thread, which is mandatory.
Just reset to zero once you reach the end:
final File file[]=dir.listFiles();
iv.postDelayed(
new Runnable() {
#Override
public void run() {
if (i == file.length) {
i = 0;
}
else {
i++;
}
Bitmap bitmap = decodeFile(file[i]);
iv.setImageBitmap(bitmap);
iv.postDelayed(this, 5000);
}
}, 5000);
Related
I am encoding a bitmap to base64.
after i pick the image from image picker, and set it to imageView, i convert it to base64. which i carry out on background thread.
It gives me the same feel as if i am carrying out the operation on UI thread itself. i.e. my UI freezes for 10-20 secs until the encoding is complete.
what can be done? so that my UI doesnt freezes.
where am i going wrong?
My function to display the chosen image in imageView
private void showSelectedImage(Uri selectedImageUri) {
blurred.setImageBitmap(null);
imglocation = selectedImageUri.toString();
Ion.with(this).load(selectedImageUri.toString()).asBitmap().setCallback(new FutureCallback<Bitmap>() {
#Override
public void onCompleted(Exception e, Bitmap result) {
if (e == null) {
blurred.setImageBitmap(result);
blurred.buildDrawingCache();
bitmap = blurred.getDrawingCache();
new Convert2base64().execute(bitmap);
}
}
});
}
This is my AsyncTask
private class Convert2base64 extends AsyncTask<Bitmap, Integer, String> {
protected String doInBackground(Bitmap... urls) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image = stream.toByteArray();
String img_str = Base64.encodeToString(image, 0);
return img_str;
}
protected void onPostExecute(String result) {
bio.setText("Base64 encoded String\n" + result);
}
}
EDIT
//blured is my imageView which is just a name rightnow. i am not carrying out the blurring task right now.
I set the image picked by image picker in the Imageview, Thats fine, in the main thread, next two lines, i.e. buildDrawingCache() and getDrawingCache() cannot be called in background thread and is only to be run in the UI thread, I dont get any error in the process, it works as intended. But since i carry the task on the background thread, i am expecting it not to freeze the UI when its converting the image in the background.
Remove the setText from postExecute method, if you are checking the result then rather check in logcat using Log.d("response",result);
The encoded text is a large amount of data, as Marcin correctly pointed out. That large amount you are loading back in the UI thread by calling setText. Thats what is freezing the UI and not the encoding process.
I don't know what the blurred view is, but I assume it's an ImageView that renders the image set to it as blurred. That blurring process is on your UI Thread, and thus causes the freeze.
Your code looks correct, you should profile it to find what takes so long. Ie. by using System.currentTimeMillis(). Actually, what looks strange to me is that you return this image as a string from doInBackground, this will be a very long string - and then you put it into a TextView. Maybe this is what takes so long. So first step is to comment out this setText line in onPostExecute and see if that helps.
I have a question regarding grid views in android.
I have a grid of 5x5 images. And I want to change these images continously. Loads new set of images from the array every time.
I have a random generator function which changes the value of the mThumbIds array after it loads every time.
But I am unable to apply the new images before it needs some event to render the new set of images. Here I do not have any event. I want them to change continuously.
Can you please me.
Unable to find any solution for this.
Did you try using an AsyncTask to change your images ? The AsyncTask could change one image, then launch a new AsyncTask.
An other option is to use a Handler. That may be your best option actually. http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/
Do you mean a timer to trigger the image changing function every 2 seconds?. If so try a Handler. Something like
private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
// init grid and set first batch of images
}
protected void onResume() {
mHandler.postDelayed(mUpdateImagesTask , 2000);
}
private Runnable mUpdateImagesTask = new Runnable() {
public void run() {
// Code to change the images
// call me in 2 seconds...
mHandler.postDelayed(this, 2000); // 2 seconds
}
};
If you want to stop the loop just put some conditions to call Handler.postDelayer() inside mUpdateImagesTask or call mHandler.removeCallbacks(mUpdateImagesTask) from outside the Runnable (at a button click, i.e).
I'm developing a small game on Android and I have a question. I want my main game loop to be the thread that is called from the SurfaceView but every time I want to call a method of another class from this thread I get the "stopped unexpectedly" message.
To be more clear:
#Override
public void run() { //Game Loop
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
grub.updateGrubber(); //here I want to update state.
mPanel.doDraw(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
the line grub.updateGrubber(); show the error that I mention before. I tried different methods from that class and all of them gives me the same error.
Any help will be appreciated.
If my guess is correct, you are trying to update the UI thread directly. You can't call UI methods from threads other than the main thread. Try:
Runnable action = new Runnable() {
#Override
public void run() {
grub.updateGrubber();
} };
this.post(action);
instead of your `grub.updateGrubber();` line.
I'm actually tested what you suggested and is not a bad idea, but the problem in my code was that I never really created a Grubber object (I miss the = new Grubber(); part).
Probably a mistake related with the enormous amount of code writing and testing that I've done in the past few weeks, sorry about that. Anyway I'm going to use as main game loop the thread that is created to update the canvas in the surfaceview according to what i've read here.
I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();
I am now working on an android app in which I need to display a text after some processing is done.
I'm using a Thread to run a process in the back while my progress dialog is being displayed to the user. The Thread works properly and I've followed it step by step and, apparently, it also ends fine; however, the method in which I call it does not seem to come to an end (at least, during a normal cycle) because the text I am setting afterward does display immediately, I have to wait and do some other action (like in order for it to display
Below is the piece of code I'm having trouble with:
private OnClickListener saldoDisp = new OnClickListener(){
public void onClick(View v){
int x = s2.getSelectedItemPosition();
branchSel = arrSucsId[x];
mainProc();
saldoAdminTex.setText(strSaldo); //The late one
}
};
public void mainProc(){
chekP = new Thread (null,doProc,"Background");
chekP.start();
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true, false);
}
private Runnable doProc = new Runnable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
};
So I do get the "Task completed properly" but seems like it still waits for something else, any clues guys?
Thanks for taking a bit of your time to check it out =).
saldoAdminTex.setText(strSaldo); //The late one
is going to get called immediately. It doesn't wait until after the Thread started in mainProc ends. You also cannot dismiss the Progress Dialog in your runnable. You can only do UI related things on the main UI thread.
It would help you to read the article on Painless Threading on the Android Dev site.
About your ProgressDialog, please see this answer about how to use a AsyncTask with a ProgressDialog.
Looking at your code, this:
saldoAdminTex.setText(strSaldo);
would potentially be executed before your thread finishes as the thread will be running in parallel to that line.
An alternative way would be to do this:
public void mainProc(){
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true,false);
handler.post(new Runable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
saldoAdminTex.setText(strSaldo);
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
});
}