Handler wont SetText on Button - android

In my Application I am trying to simply setText() on my Button purchaseButton.
I have an Alert Dialog that takes a value and initializes an AsyncTask to complete the server call to find the discount.
All of that works fine, its when I get to the onPostExecute().
onPostExecute():
protected void onPostExecute(String result) {
Log.d(tag,"Result of POST: " + result);
if(result != null){
if(result.equals("NO")){
createAlert(1);
}else{
result = result.replaceAll("YES", "");
String discount = result;
discountPrice = price - Double.parseDouble(discount);
Log.d(tag, "Discount price after pull:" + discountPrice);
//setPurchase("Purchase $" + String.valueOf(discountPrice));
new Thread(new Runnable()
{
#Override
public void run()
{
Message msg = handler.obtainMessage();
msg.what = (int) discountPrice;
handler.sendMessage(msg);
}
}).start();
}
}
You can see that I make a call to a handler from a new Thread(). This allows me to get to the handler but never sets the text of the button from the handler.
Handler Method:
final static Handler handler = new Handler(){
#Override
public void handleMessage(Message msg){
Log.d(tag, "entered handler");
if(msg.what == discountPrice)
{
setPurchaseText(msg.what);
}
}
};
setPurchaseText() method:
private static void setPurchaseText(int value){
Log.d(tag, "Entered setPurchaseText");
purchaseButton.setText("Purchase $" + String.valueOf(value));
}
From my knowledge this should allow me to set the text from the handler. Why is it not setting the text and how can I get it to set the text with my string value?
Any help is much appreciated!

If the setText() is not working in onPostExecute(), they you might not be creating your AsyncTask on the UI thread. AsyncTask runs onPostExecute() on the thread you create it.
Again, Handler is created on the currently executed Thread. May be your Handler is initialized on a background thread. Try using final static Handler handler = new Handler(Looper.getMainLooper()). This ensures the handler to be attached to the main thread.

Related

Android thread encapsulation, cannot get changing variables from the encapsulated class

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.

ProgressDialog does not always show up

My application works as a BluetoothServer, almost the same as the BluetoothChat example. I'm facing a strange problem. Inside my run-method where I start reading input from the bluetoothSocket, I want to post a message to a handler. This handler is in a seperate class, to avoid possible memory leaks.
public void run() {
Log.i("", "BEGIN ReadInputThread");
final byte[] buffer = new byte[1024];
int bytesread;
Message msg = handler.obtainMessage();
msg.obj = "0";
handler.sendMessage(msg);
...... snip .....
When I receive the String "0", in my handler, I want to show a progressDialog that informing the user that the application has an incoming file. In my handler, this is how I deal with it:
public class MessageHandler extends Handler {
#Override
public void handleMessage(Message m) {
Vibrator v = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE);
String message = (String) m.obj;
//Getting files
if (message.equals("0")) {
folder.appendToLogFile(new Date().toString(), "Incoming File From: " + deviceName);
v.vibrate(1500);
pd = new ProgressDialog(c);
pd.setTitle("Please Wait..");
pd.setMessage("Retrieving file from " + deviceName);
pd.setCancelable(false);
pd.show();
}
}
The first time, when I have my Activity open, which will start this Thread, the progressDialog will show. After the transfer has finished, I navigate to a new Activity, and then returning to the previous Activity. When I now try to transfer a file, it will succeed, but no ProgressDialog is shown on the screen.
I did some checks just to figure out if the ProgressDialog is "visible" by adding these two lines under the pd.show() statement
if(pd.isShowing())
Log.w("Handler: ", "inside the handler, and the progressdialog is showing");
And this also appears in LogCat, even if the ProgressDialog is not showing!
Can anybody give me a hint, or a solution to this frustration issue?
Thanks in advance!
Just to clarify a bit
My ProgressDialog is created in a class which not extends Activity, it doesn't extend any classes.
The first thing I do, is to post a 0 to my handler, in the start of my run() method. When I know that I have received the last byte-packet from the socket, I send another message to the handler:
if(lastPacket) {
msg = handler.obtainMessage();
msg.obj = "1";
handler.sendMessage(msg);
}
And in my Handler:
#Override
public void handleMessage(Message m) {
Vibrator v = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE);
String message = (String) m.obj;
//Getting files
if (message.equals("0")) {
folder.appendToLogFile(new Date().toString(), "Incoming File From: " + deviceName);
v.vibrate(1500);
pd = new ProgressDialog(c);
pd.setTitle("Please Wait..");
pd.setMessage("Retrieving file from " + deviceName);
pd.setCancelable(false);
pd.show();
if(pd.isShowing())
Log.w("Handler: ", "inside the handler, and the progressdialog is showing");
}
//File complete
if(message.equals("1")) {
Toast.makeText(c, "File Received from: " + deviceName, Toast.LENGTH_LONG).show();
folder.appendToLogFile(new Date().toString(), "File Received");
pd.setMessage(c.getResources().getString(R.string.createCase));
GenerateCase caseGenerator = new GenerateCase(c, pd, lastCases, nextPCN);
caseGenerator.execute("");
}
}
as you can see, I pass the ProgressDialog into the AsyncTask. In my onPostExecute method, I dismiss this ProgressDialog
Solution
If someone is curious. I got confused with the threads. When I left my Activity, I forgot to kill my running thread, which would cause the ProgressDialog to start in a different thread when I resumed my activity.
Close your progress dialog via broadcast Intent;
onPostExecute(){
sendBroadcastIntent(new Intent("ACTION_CLOSE_DIALOG"):
}
BroadCastReceiver receiver = new BroadCastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if(pd.isShowing()){
pd.dismiss();
}else{
pd.show()
}
}
}
call Broadcast here:
pd.show();// call broadcast instead pd.show() use sendBroadcastIntent(new Intent("ACTION_CLOSE_DIALOG")

Thread problem in android?

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();
}
}

Several setMessage updates (ProgressBar)

new Thread() {
public void run() {
try {
Progress.setMessage("Scanning Apps ...");
int CurrentNumber = 0;
while (CurrentNumber <= 99) {
Progress.setProgress(CurrentNumber);
Progress.setMessage(CurrentNumber + "");
sleep(100);
CurrentNumber ++;
} catch (Exception e) {
}
}
}.start();
So.. this code is not working :(
What am I doing wrong?
Without Progress.setMessage(CurrentNumber + ""); it is working perfectly...
write handler
e.g.
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//set message here
}
};
Try looking at AsyncTask which handles progress updates, giving you a chance to set your progress message on the UI thread.
I'm assuming that Progress is an instance of ProgressDialog. You can only update the UI on the UI (main) thread. Read about threading and the UI on the dev site.

Pass a Message From Thread to Update UI

Ive created a new thread for a file browser. The thread reads the contents of a directory. What I want to do is update the UI thread to draw a graphical representation of the files and folders. I know I can't update the UI from within a new thread so what I want to do is:
whilst the file scanning thread iterates through a directories files and folders pass a file path string back to the UI thread. The handler in the UI thread then draws the graphical representation of the file passed back.
public class New_Project extends Activity implements Runnable {
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("New Thread","Proccess Complete.");
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
}
};
public void fileScanner(){
//if (!XMLEFunctions.canReadExternal(this)) return;
pd = ProgressDialog.show(this, "Reading Directory.",
"Please Wait...", true, false);
Log.d("New Thread","Called");
Thread thread = new Thread(this);
thread.start();
}
public void run() {
Log.d("New Thread","Reading Files");
getFiles();
handler.sendEmptyMessage(0);
}
public void getFiles() {
for (int i=0;i<=allFiles.length-1;i++){
//I WANT TO PASS THE FILE PATH BACK TU A HANDLER IN THE UI
//SO IT CAN BE DRAWN.
**passFilePathBackToBeDrawn(allFiles[i].toString());**
}
}
}
It seems passing simple messages is int based... What I needed to do was pass a Bundle
using Message.setData(Bundle) and Message.getData(Bundle)
So Happy =0)
//Function From Within The Thread
public void newProjectCreation() {
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("Test", "test value");
msg.setData(bundle);
handler2.sendMessage(msg);
}
//Handler in The UI Thread Retreieves The Data
//And Can Update the GUI as Required
private Handler handler2 = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
Toast.makeText(New_Project.this,bundle.getString("Test"),Toast.LENGTH_SHORT).show();
}
};
Check out AsyncTask for this kind of stuff. It's really much more elegant than rolling your own handler and passing messages back and forth.
http://developer.android.com/reference/android/os/AsyncTask.html

Categories

Resources