I am trying to load an object from a server in Android. This object is loaded in a thread. When loading is finished, an _objectHandler is called to get some key - values from the object, for example, the _filename key. Every time a filename is retrieved, I want to display it. For this reason, I am looping over the element of the loaded object in a second thread, and calling a _handler every time a value is loaded. What I want to get is all the _filename values, but what I am getting is only the last value of the _fielName. what I am doing wrong?
ArrayList <myObject> object;
String filename;
Thread thread = new Thread (MyActivity.this);
thread.start();
public void run() {
Looper.prepare();
try {
object = getObjectFromServer();
} catch (Exception e) {
e.printStackTrace();
}
_objectHandler.sendEmptyMessage(0);
Looper.loop();
}
Handler _objectHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
for (int i = 0; i < object.size(); i++) {
myObject obj= object(i);
new Thread(new Runnable() {
public void run() {
filename= obj.getFileName();
Message msg = new Message();
_handler.sendEmptyMessage(0);
}
}).start();
}
}
};
Handler _handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.i("The fielname is ", " filename" + filename
}
};
you can use android.os.Handler class. This will provide you a mechanism for enqueue an action to be performed on a different thread than your own.
Related
I have a code running inside the Thread. I tried to use the handler to do receive the message from the thread so i can update the UI. Unfortunately, the message didn't get send to the handler.
This is my code snippet inside the run method of the Thread
ChromaticLayout chromatic = new ChromaticLayout(mPartition, mDeviceWidth, mDeviceHeight, mData);
chromatic.execute(new ChromaticLayout.LayoutCallback() {
#Override
public synchronized void retrieveResult(Object[][] data) {
// TODO Auto-generated method stub
mPhotoData.clear();
Log.w("CALLBACK", "start");
for (int i=0; i<data.length; i++)
{
PhotoFrameData[] row = new PhotoFrameData[data[i].length];
for (int j=0; j<data[i].length; j++) {
if (j==0)
Log.w("CALLBACK", "Width = " + ((PhotoFrameData) data[i][j]).getRectangle().width() + " height = " + ((PhotoFrameData) data[i][j]).getRectangle().height() );
row[j] = (PhotoFrameData) data[i][j];
}
mPhotoData.add(row);
}
Log.w("CALLBACK", "end");
PhotoFrameAdapter.this.handle.post(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
PhotoFrameAdapter.this.handle.sendEmptyMessage(1);
} });
//if (!PhotoFrameAdapter.this.handle.sendEmptyMessage(1))
// Log.w("CALLBACK", "Handle not working");
}});
}
The is the receiving message of the handler:
protected Handler handle = new Handler() {
public void handleMessage(Bundle message) {
//PhotoFrameAdapter.this.notifyDataSetChanged();
mListener.dataLoaded(this);
}
};
What make it not adding to the message queue and call the handleMessage? Thanks
try this:
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
//do staff
break;
}
};
};
Another way you can use a Handler is as follows (it's perhaps a simpler implementation in many cases):
Define the hander on the UI thread:
private Handler mHandler = new Handler();
Then from your background thread just post a Runnable with the code you want to run:
mHandler.post(new Runnable() {
#Override
public void run() {
// Code to run here
}
});
I have an application which starts a new service. In this service I currently have a handler that does some work every minute and then sends the results to the main activity through a BroadcastReceiver. I want the following thing: Every minute create a new thread inside the service, make it do the work and send a message to the handler that it is finnished and then the handler will send to the main activity through a BroadcastReceiver. How can i combine the Thread and the Handler? Here is what I have so far -only part of code of interest-
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
try {
getAppResources(); //this is the work i want to place in a new thread
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
intent.putExtra(key,value);
sendBroadcast(intent);
handler.postDelayed(this, 60*1000);
}
};
Here is what i understand i need to do
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
/* try {
getAppResources();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
Thread t = new Thread() {
#Override
public void run(){
try {
getAppResources();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
};
handler.postDelayed(this, 60*1000);
}
};
And where do i place the handleMessage ? If i place it inside the Runnable it says it is never used locally. I just place it right before the Runnable ?
public void handleMessage(Message msg){
if(msg.what == 0){
intent.putExtra(key,value);
sendBroadcast(intent);
}
}
Is this how I should do it ?
EDIT: Handler code that sends to the main activity some data
private final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == 0){
Log.d("HANDLE","Am primit mesaj");
//Notify preparations
intent.putExtra("RunningApps", runningApps.size());
intent.putExtra("CPU", highestDrainPackageCPU);
intent.putExtra("GPS",highestDrainPackageGPS);
intent.putExtra("WIFI", highestDrainPackageWIFI);
//Now i have all my data, time to send them to the activity
//First , send the strings to be set in the TextViews
//Each running app has 7 messages to display -> ArrayList<String>
for(int i=0;i<runningApps.size();i++){
intent.putStringArrayListExtra(String.valueOf(i), appInfo.get(i));
}
//Next send values to plot the chart
//CPU energy consumption for highest draining application
double [] currValues_cpu = new double[tableCPU.get(highestDrainPackageCPU).size()];
Log.d("CPUSIZE",String.valueOf(currValues_cpu.length));
for(int j=0;j<tableCPU.get(highestDrainPackageCPU).size();j++){
currValues_cpu[j]=tableCPU.get(highestDrainPackageCPU).get(j);
Log.d("CPUVALUE",String.valueOf(currValues_cpu[j])+"For application"+highestDrainPackageCPU);
}
intent.putExtra("highestDrainPackageCPU", currValues_cpu);
//GPS energy consumption for highest draining application
double [] currValues_gps = new double[tableGPS.get(highestDrainPackageGPS).size()];
for(int j=0;j<tableGPS.get(highestDrainPackageGPS).size();j++){
currValues_gps[j]=tableGPS.get(highestDrainPackageGPS).get(j);
}
intent.putExtra("highestDrainPackageGPS", currValues_gps);
//WIFI energy consumption for highest draining application
double [] currValues_wifi = new double[tableWIFI.get(highestDrainPackageWIFI).size()];
for(int j=0;j<tableWIFI.get(highestDrainPackageWIFI).size();j++){
currValues_wifi[j]=tableWIFI.get(highestDrainPackageWIFI).get(j);
}
intent.putExtra("highestDrainPackageWIFI", currValues_wifi);
sendBroadcast(intent);
}
}
};
Here is the BroadcastReceiver in the Main Activity and the UpdateUI function:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
public void updateUI(Intent intent){
resourceTab.removeAllViews();
//statisticsTab.removeAllViews();
int apps_no = intent.getIntExtra("RunningApps", 0);
String highestDrainPackageCPU = intent.getStringExtra("CPU");
String highestDrainPackageGPS = intent.getStringExtra("GPS");
String highestDrainPackageWIFI = intent.getStringExtra("WIFI");
//TO-DO: Get information for each app and store it in textview.Then add it to a linearlayout
for(int i=0;i<apps_no;i++){
//Setup delimiter
View delimitator = new View(this);
delimitator.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,1));
delimitator.setBackgroundColor(Color.parseColor("#50FFFFFF"));
//Extract values
ArrayList<String> info = new ArrayList<String>();
info=intent.getStringArrayListExtra(String.valueOf(i));
for(int j=0;j<info.size();j++){
TextView infoApp = new TextView(this);
//////Setup textview//////////
infoApp = new TextView(this);
infoApp.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
infoApp.setTextColor(Color.parseColor("#FFFFFF"));
infoApp.setText(info.get(j));
resourceTab.addView(infoApp);
}
//Add delimiter
resourceTab.addView(delimitator);
}
double [] cpu_values = intent.getDoubleArrayExtra("highestDrainPackageCPU");
double [] gps_values = intent.getDoubleArrayExtra("highestDrainPackageGPS");
double [] wifi_values = intent.getDoubleArrayExtra("highestDrainPackageWIFI");
//Now plot the graph
createGraphOverall(cpu_values, gps_values, wifi_values, highestDrainPackageCPU, highestDrainPackageGPS, highestDrainPackageWIFI);
//Update the table
updateTable(cpu_values, gps_values, wifi_values, highestDrainPackageCPU, highestDrainPackageGPS, highestDrainPackageWIFI);
}
My Activity was successfully updated before I tried to create a new thread to do the heavy work inside the service.
EDIT: Sorry, I think I noticed it earlier, and got side tracked with the handler.
You create Thread t, but you never run it.
t.start();
You define handleMessage() as a method of the handler, like this:
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//TODO: Handle different types of messages
}
};
I want to write a download manager app, in the activity I add a progress bar which show the current progress to the user, now if user touch the back button and re-open the activity again this ProgressBar won't be updated.
To avoid from this problem I create a single thread with unique name for each download that keep progress runnable and check if that thread is running in onResume function, if it is then clone it to the current thread and re-run the new thread again but it won't update my UI either, Any ideas !?
#Override
public void onResume()
{
super.onResume();
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
for (int i = 0; i < threadArray.length; i++)
if (threadArray[i].getName().equals(APPLICATION_ID))
{
mBackground = new Thread(threadArray[i]);
mBackground.start();
downloadProgressBar.setVisibility(View.VISIBLE);
Toast.makeText(showcaseActivity.this
, "Find that thread - okay", Toast.LENGTH_LONG).show();
}
}
private void updateProgressBar()
{
Runnable runnable = new updateProgress();
mBackground = new Thread(runnable);
mBackground.setName(APPLICATION_ID);
mBackground.start();
}
private class updateProgress implements Runnable
{
public void run()
{
while (Thread.currentThread() == mBackground)
try
{
Thread.sleep(1000);
Message setMessage = new Message();
setMessage.what = mDownloadReceiver.getProgressPercentage();
mHandler.sendMessage(setMessage);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
catch (Exception e)
{/* Do Nothing */}
}
}
private Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message getMessage)
{
downloadProgressBar.setIndeterminate(false);
downloadProgressBar.setProgress(getMessage.what);
if (getMessage.what == 100)
downloadProgressBar.setVisibility(View.GONE);
}
};
Download button code:
downloadBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
downloadProgressBar.setVisibility(View.VISIBLE);
downloadProgressBar.setIndeterminate(true);
downloadProgressBar.setMax(100);
Intent intent = new Intent(showcaseActivity.this, downloadManagers.class);
intent.putExtra("url", "http://test.com/t.zip");
intent.putExtra("receiver", mDownloadReceiver);
startService(intent);
updateProgressBar();
}
});
I'd strongly recommend reading the Android Developer blog post on Painless Threading. As it states, the easiest way to update your UI from another thread is using Activity.runOnUiThread.
I am quite new to Android and Java. Basically, I would like to realize an encapsulation of a background thread of Android, and inside this background thread, I have an infinite loop which will periodically take some operations of getting data(like from Internet, or from some hardware devices).
The encapsulated class must provide only a function like getData() for others to get data. But everytime when i call this getData() function from other classes, it never gives me the changing values, but only the initialized values.
I've studied both of the AsyncTask, Handler and Message ways to realize multithread. And both of them give me the initialized values.
Here is the encapsulated class of Handler and Message:
public class getDataFromUSB{
private int usb_data;
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==1){
usb_data=msg.arg1;
}
}
};
private Thread thread = new Thread(){
#Override
public void run(){
while(!Thread.currentThread().isInterrupted())
{
int a=read_usb();
Message msg = new Message();
msg.arg1 = a;
msg.what = 1;
handler.sendMessage(msg);
try {
Thread.sleep(15);
} catch (InterruptedException e) {
System.err.println("");
this.interrupt();
}
}
}
};
public void start(){
thread.start();
}
public int get_data(){
return usb_data;
}
public int read_usb()
{
int a=10;
return a;
}
}
And then in another class, here is the code of calling getDataFromUSB:
getDataFromUSB usb1= new getDataFromUSB();
usb1.start();
int a=usb1.getData();
Log.e(TAG,"a = " +a);
Then everytime i call this usb1.getData(), the value is always 0. I don't understand why.
Now I proceed to do some more realistic things. I add an object of random in my getDataFrom USB class to provide different numbers, I also change the way of assigning values to usb_data, I think it's better to do it just in the background thread, there is no need to move it to the handlemessage. So it becomes:
public class getDataFromUSB{
private int usb_data;
private Random random = new Random(555L);
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
private Thread thread = new Thread(){
#Override
public void run(){
while(!Thread.currentThread().isInterrupted())
{
int a=read_usb();
usb_data=a;
Message msg = new Message();
handler.sendMessage(msg);
}
}
};
public void start(){
thread.start();
}
public int get_data(){
return usb_data;
}
public int read_usb()
{
return random.nextInt();
}
}
Then I call it from another class like what Nikita suggested:
Handler h = new Handler();
for (int i=0;i<20;i++){
h.postDelayed(new Runnable() {
public void run() {
int data=usb1.get_data();
Log.e(TAG,"data= " +data);
}
},500);
}
The strange thing is that it then gives sometimes all the same numbers, sometimes several some numbers, sometimes all different numbers. As I understand, the usb_data has always been changed inside the background thread, so we are not obliged to wait for handlemessage to proceed. Everytime I call getData(), it should give me the newest value. Isn't that right?
The problem might be following: you run your code from main UI thread. When you new start thread - it sends message to handler. This message is added to main thread's queue and will be processed in main thread when it finishes it's current job. Currently main thread runs your code and there is no chance that message will be processed before you call usb.getData().
To check whether your update thread works properly you can post delayed runnable that will print value of usb1.getData():
final getDataFromUSB usb1= new getDataFromUSB();
usb1.start();
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
int a=usb1.getData();
Log.e(TAG,"a = " +a);
}
}, 500); // Waits 500 milliseconds and runs runnable on current thread.
Consider i have one thread as a separate class , for example SimpleThread.java,
class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
from my android home.java i need to start the thread,
new SimpleThread("Jamaica").start();
once the loop end i need to shoe the alert,but when i use
authalert = new AlertDialog.Builder(this);
it shows null pointer execption, i need a context over here in thread class , is there any other way to do this.
Hey you should use Handler for this
here is the code ...
ProgressDialog _progressDialog = ProgressDialog.show(this,"Saving Data","Please wait......");
settintAdater();
private void settingAdater(){
Thread _thread = new Thread(){
public void run() {
Message _msg = new Message();
_msg.what = 1;
// Do your task where you want to rerieve data to set in adapet
YourCalss.this._handle.sendMessage(_msg);
};
};
_thread.start();
}
Handler _handle = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
_progressDialog.dismiss();
listview.setAdapter();
}
}
}
One way of solving your problem is using Handlers, as Sujit suggested. Other way is using AsyncTask. Read here.
the problem is : when you launch the thread, the Compiler will not wait until the thread finish his treatement , he will execute the next instruction ( authalert = new AlertDialog.Builder(this); )
so there are two or three ways to do this :
1) , use handler
2) define your own listener for your thread in order to listen until he finished his treatement ,
3) you can pass the Context of your activity , and at the last line of your run method , display the AlertDialog ( with Activity.runOnUiThread(new Runnable); )
You should read http://www.aviyehuda.com/2010/12/android-multithreading-in-a-ui-environment/ and http://developer.android.com/resources/articles/painless-threading.html
one way would be put a handler in your calling activity:
final mContext=this;
final Handler mHandler=new Handler(){
#Override
public void handleMessage(Message msg) {
int yourIntReturnValue=msg.what;
//cast your object back to whatever it was lets say it was a string:
// String yourString=(String) msg.obj;
//do something like authalert = new AlertDialog.Builder(mContext);
}
};
then
class SimpleThread extends Thread {
Handler mHandler;
public SimpleThread(String str, Handler h) {
super(str);
mHandler=h;
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
Message.obtain(mHandler, someIntRetValue,
"DONE" ).sendToTarget();
}
}