I'm trying to develop an app which gets some data from an HTML webpage and displays it every second.
For that i'm using a runnable in this way:
In the OnCreate() method:
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(mMuestraMensaje, 5000);
And then this other method:
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
rowTextView.setText(returned);
} catch (Exception e) {
e.printStackTrace();
}
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(this, 500);
}
};
The problem is that if i press the back button, for example, the app starts to behave slowly and until i don't force close the whole app the device runs too slow!
Thank you!
EDIT
This is the whole class:
public class HttpExample extends Title {
GetMethodEx test, moredata ;
String returned;
TextView rowTextView, rowTextView2;
LinearLayout ll;
private Handler mHandler = new Handler();
String newString;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.httpexample);
rowTextView = (TextView)findViewById(R.id.textView2);
rowTextView2 = (TextView)findViewById(R.id.textView1);
mHandler.removeCallbacks(mMuestraMensaje);
mHandler.postDelayed(mMuestraMensaje, 5000);
Bundle extras = getIntent().getExtras();
newString = extras.getString("STRING_I_NEED");
test = new GetMethodEx();
moredata = new GetMethodEx();
try {
String name = moredata.GetName(newString);
rowTextView2.setText(name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(mMuestraMensaje , 0, 500, TimeUnit.MILLISECONDS );
}
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable(){
rowTextView.setText(returned);
});
}
};
}
Your program slows down because you are running the thread on the GUI thread. That isn't recommended. However, I notice you are setting text after you are done. Here's a few things you could do.
Run the sensor data gathering in a different thread. Update the text by the runOnUiThread command.
Use an AsyncTask, this seems to be an ideal situation for one.
For such a regular occurrence, that doesn't require a UI thread, I would suggest using a ScheduledExecutorService.
The simplest to start with would be the first, but I would look carefully at the second option. The first option would be something like this: (Note, you will need to replace MainActivity with the name of your activity)
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(mMuestraMensaje , 0, 500, TimeUnit.MILLISECONDS );
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable(){
rowTextView.setText(returned);
});
}
};
You can attach you Handler to work on a different thread by using HandlerThread. For example:
HandlerThread ht = new HandlerThread("nonUiThread");
ht.start();
Handler mHandler = new Handler(ht.getLooper());
but more preferably, I would suggest you to use AsyncTask in your case.
Got it to work with this:
private Runnable mMuestraMensaje = new Runnable() {
public void run() {
try {
returned = test.GetSensorData(newString);
} catch (Exception e) {
e.printStackTrace();
}
HttpExample.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
rowTextView.setText(returned.get(0)+returned.get(1));
rowTextView2.setText(returned.get(2));
}
});
}
};
Related
Right now I'm simulating the showing of a ProgressDialog for an event that is expected to take several seconds.
I'm doing it this way:
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage(getString(R.string.calendar_load));
progressDialog.setCancelable(false);
progressDialog.show();
Thread t=new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run() {
progressDialog.cancel();
progressDialog.hide();
But even though I've checked in debug that the progressDialog.cancel() and progressDialog.hide() execute the dialog just keeps on showing apparently in an indefinite way.
What could be causing such behavior?
PROBLEM SOLVED: Thanks to everyone who has answered/commented, it looks like an emulator bug (indeed it has also worked some times on emulator).
Call progressDialog.dismiss();
Could you try this snippet?
progressDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (progressDialog.getProgress() <= progressDialog.getMax()) {
Thread.sleep(100);
handle.sendMessage(handle.obtainMessage());
if (progressDialog.getProgress() == progressDialog.getMax()) {
progressDialog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDialog.incrementProgressBy(1);
}
};
I have a button and when clicked calls a method which starts a thread. but there is stop for that thread, fine. I want that to complete the thread first then to execute the rest of the code.
I tried to use wait() but not working.
public void configure(Button arg0,TextView arg1) throws InterruptedException{
//calling OpenDeviceListener
readText=arg1;
button= arg0;
//handler
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("Handler","running");
if (actualNumBytes != 0x00) {
Log.d("handler","if");
readText.append(String.copyValueOf(readBuffer, 0,
actualNumBytes));
Log.d("handler","if 312");
actualNumBytes = 0;
Log.d("handler","if end");
}
Log.d("handler","closed");
}
};
Log.d("163","tab");
uartInterface = new CH34xAndroidDriver(
(UsbManager) getSystemService(Context.USB_SERVICE), this,
ACTION_USB_PERMISSION);
Log.d("167","tab");
act_string = getIntent().getAction();
if(-1 != act_string.indexOf("android.intent.action.MAIN"))
{
Log.d(TAG, "android.intent.action.MAIN 171");
}
else if(-1 != act_string.indexOf("android.hardware.usb.action.USB_DEVICE_ATTACHED"))
{
Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_ATTACHED 175");
}
if(!uartInterface.UsbFeatureSupported())
{
Toast.makeText(this, "No Support USB host API", Toast.LENGTH_SHORT).show();
Log.d("182","tab");
readText.setText("No Support USB host API");
Log.d("184","tab");
uartInterface = null;
}
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
if(READ_ENABLE == false) {
READ_ENABLE = true;
Log.d("192","tab");
handlerThread = new readThread(handler);
handlerThread.start();
}
Log.d("192","End");
try{
this.wait(100);
}
catch(InterruptedException e){
e.printStackTrace();
Log.d("Exception",e.getMessage());
}
// TODO Auto-generated method stub
Log.d("205","OpenDeviceListener");
boolean flags;
if(false == isConfiged) {
Log.d("209","OpenDeviceListener");
Toast.makeText(global_context,""+((Boolean)uartInterface.isConnected()), Toast.LENGTH_LONG).show();
isConfiged = true;
// writeButton.setEnabled(true);
if(uartInterface.isConnected()) {
Toast.makeText(global_context,""+(Boolean)uartInterface.isConnected(), Toast.LENGTH_SHORT).show();
Log.d("213","OpenDeviceListener");
flags = uartInterface.UartInit();
if(!flags) {
Log.d(TAG, "Init Uart Error 2");
Toast.makeText(global_context, "Init Uart Error", Toast.LENGTH_SHORT).show();
} else {
if(uartInterface.SetConfig(baudRate, dataBit, stopBit, parity, flowControl)) {
Log.d(TAG, "Configed");
}
}
}
}
}
and plz clear one thing the stop() is not called for the thread, up to when the thread will run.
Thanks
final Runnable runnable = new Runnable() {
#Override
public void run() {
//this method will be called after 2 seconds
//do your task here
}
};
final Handler h = new Handler();
h.removeCallbacks(runnable); // cancel the running action (the
// hiding process)
h.postDelayed(runnable, 2000);
try this:
Object lock = new Object;
synchronized(lock){
lock.wait();
}
this will block current Thread running these code.
when it's time notify the blocked code
synchronized (lock) {
lock.notify();
}
if just want to sleep the thread for a specific time why not use
Thread.sleep(1000);
I am using Jsoup to parse a part of a website and then put it into a string. I want to visualize this string into a textView, but since only the thread that had created the textView can modify it i need to pass the value of the string into the main thread. how?
This is the code: (ignore the tabhost stuff)
public class NewsAndAnnouncements extends Activity {
TabHost host;
FlyOutContainer container;
Button bttoggle;
Button bt1;
String loggity;
TextView tv1;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.container = (FlyOutContainer) this.getLayoutInflater().inflate(
R.layout.newsandannouncements, null);
this.setContentView(container);
host = (TabHost) findViewById(R.id.tabhost);
host.setup();
TabSpec specs = host.newTabSpec("TAGGITY EINZ");
specs.setContent(R.id.tab1);
specs.setIndicator("News");
host.addTab(specs);
specs = host.newTabSpec("TAGGITY ZWEI");
specs.setContent(R.id.tab2);
specs.setIndicator("Notices");
host.addTab(specs);
specs = host.newTabSpec("TAGGITY DREI");
specs.setContent(R.id.tab3);
specs.setIndicator("Events");
host.addTab(specs);
tv1 = (TextView) findViewById(R.id.textView1);
/*
* bttoggle = (Button) findViewById(R.id.bttoggle); bt1 = (Button)
* findViewById(R.id.Button1);
*
* bttoggle.setOnClickListener(new OnClickListener() {
*
* #Override public void onClick(View v) { // TODO Auto-generated method
* container.toggleMenu(); } });
*
* bt1.setOnClickListener(new OnClickListener() {
*
* #Override public void onClick(View v) { // TODO Auto-generated method
* container.toggleMenu(); } });
*/
Thread newsThread = new Thread() {
public void run() {
Document doc = null;
try {
doc = Jsoup
.connect(
"http://acs.bg/Home/About_ACS/News_and_Events/News.aspx")
.get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Elements myin = doc.getElementsByClass("news_list");
loggity = myin.toString();
Log.i("ELEMENTS HTML", loggity);
}
};
newsThread.start();
tv1.setText(loggity);
}
}
Try using AsyncTask instead of the Thread. To modify views on your ui thread use the runOnUiThread() method in your activity.
runOnUiThread(new Runnable() {
#Override
public void run() {
tv1.setText("...");
}
});
Use an AsyncTask instead of a raw Thread:
new AsyncTask<URL, Object, Document>() {
protected Document doInBackground(URL... urls) {
// parse URL and return document
}
protected void onPostExecute(Document result) {
// this runs in UI thread
// show document in UI
}
}).execute(myURL);
There are two ways to d it-
1)- Using AsyncTask
2)- Using Handler
Thread newsThread = new Thread()
{
public void run()
{
Document doc = null;
try {
doc = Jsoup
.connect(
"http://acs.bg/Home/About_ACS/News_and_Events/News.aspx")
.get();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Elements myin = doc.getElementsByClass("news_list");
loggity = myin.toString();
mHandler.post(new Runnable()
{
#Override
public void run()
{
try
{
tv1.setText(loggity);
} catch (Exception e)
{
e.printStackTrace();
}
}
});
Log.i("ELEMENTS HTML", loggity);
}
};
newsThread.start();
You can initialize the Hanlder in the start.
try this sample code, don't know if this is the better way:
public class MainThread {
public static void main(String args[]) {
Thread2 t2 = new Thread2();
Thread nextThread = new Thread(t2);
nextThread.start();
try {
nextThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
System.out.println(t2.getStr());
}
private static class Thread2 implements Runnable{
private String str;
#Override
public void run() {
setStr("T2 Thread String");
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
}
I am creating an application in which user can start slideshow (auto-play) of images by clicking a specific button. I have started a thread in which a new image is set to my imageView after a 1 sec. Problem is that my app stop responding and crashes after few seconds.
Please check my code and help me to resolve this issue. (variables are correctly initialized)
playThread = new Runnable() {
#Override
public void run() {
synchronized (this) {
for (int i=pos;i<mImageIds.length;i++){
//pos++;
selectedImage.setImageResource(mImageIds[i]);
try {
wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}
}};
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
runOnUiThread(playThread);
}
});
}
my logcat while app freezes!
The runOnUiThread() method is meant to update the user interface. Any other logic shouldn't happen there. So I would suggest something like this:
Thread t = new Thread() {
for (int i=pos;i<mImageIds.length;i++){
runOnUiThread(new Runnable() {
#Override
public void run() {
selectedImage.setImageResource(mImageIds[i]);
}};);
try {
wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
t.start();
}
});
Please note, I didn't test this code.
I am trying to show error messages and hide them after 3 seconds. That's what I have written but it seems that it doesn't work that way.
yazi.setVisibility(View.VISIBLE);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
yazi.setVisibility(View.GONE);
You can use a Handler with its postDelayed method for your purpose:
//Show your view
yazi.setVisibility(View.VISIBLE);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Hide your View after 3 seconds
yazi.setVisibility(View.GONE);
}
}, 3000);
Update your code like this
Inside your onCreate() method
yazi.setVisibility(View.VISIBLE);
Thread thread=new Thread(runnable);
thread.start();
and outside your onCreate() method , do like this
Runnable runnable=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
yazi.setVisibility(View.GONE);
}
});
}
};
};
Always use runOnUiThread for making UI operations.