protected void onCreate(Bundle savedInstanceState) {`
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.test_button);
button.setText("before");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
button.setText("after");
}
}, 2000);
}
I think this solution will not cause a memory leak. According to the answer which gets most votes (How to pause / sleep thread or process in Android?),this will cause a memory leak. what do you think?
To avoid memory leak, handler need to have WeakReference to activity. You can do it like this
private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();
public static class MyRunnable implements Runnable {
private final WeakReference<Activity> mActivity;
public MyRunnable(Activity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
public void run() {
Activity activity = mActivity.get();
if (activity != null) {
Button btn = (Button) activity.findViewById(R.id.button);
btn.setBackgroundResource(R.drawable.defaultcard);
}
}
}
private MyRunnable mRunnable = new MyRunnable(this);
public void onClick(View view) {
my_button.setBackgroundResource(R.drawable.icon);
// Execute the Runnable in 2 seconds
mHandler.postDelayed(mRunnable, 2000);
}
Same is also mentioned in https://stackoverflow.com/a/3039718/3812404
Related
I use code like below for periodic execution
but i am suspecting a memory leak
Maybe my code is wrong?
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
if(isRunning)
{
...code
}
handler.postDelayed(this, 5000);
}
};
handler.postDelayed(runnable, 5000);
This is the code that uses another handler
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
mHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(#NonNull Message msg) {
return true;
}
});
}
Wrote an application to an Android to understand the control of view items from the child thread. Took the main looper from named Mainactivity and passed it through the constructor to a class that implements a child thread and that just changes the contents of TextView through callback.
public class MainActivity extends AppCompatActivity {
private TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("create", Thread.currentThread().toString());
textView = (TextView) findViewById(R.id.textView);
HandlerTextView handlerTextView = new HandlerTextView(getApplicationContext().getMainLooper());
handlerTextView.registerMessage(new Message() {
#Override
public void handleMessage(String msg) {
textView.setText(msg);
}
});
HandlerThread handlerThread = new HandlerThread("two", HandlerThread.NORM_PRIORITY);
if(handlerThread != null){
Handler a = new Handler(handlerThread.getLooper());
if(a != null) {
a.post(handlerTextView);
}
}
}
}
public class HandlerTextView implements Runnable {
private Looper mainLooper = null;
private TextView textView = null;
private Socket socket = null;
private Message message = null;
public HandlerTextView(Looper looper) {
this.mainLooper = looper;
}
public void registerMessage(Message m) {
this.message = m;
}
private void setText(final String str) {
Handler handler = new Handler(mainLooper);
handler.post(new Runnable() {
#Override
public void run() {
message.handleMessage(str);
}
});
}
#Override
public void run() {
setText("dfsdfsdfsdf");
}
}
Created a new Handlerthread thread handler object, took it looper
and passed it to the constructor of the new handler handler and it
The error: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity
ComponentInfo{elaneturn.com.myapplication/elaneturn.com.myapplication.MainActiv Caused by: java.lang.NullPointerException
Call handlerThread.start() before creating Handler:
handlerThread.start();
Handler a = new Handler(handlerThread.getLooper());
How to do sample counter in Activity? This is not working.
public class MainActivity extends AppCompatActivity implements Runnable {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
run();
}
#Override
public void run() {
while (true) {
updateTv();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void updateTv() {
int counter = 100;
final TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(String.valueOf(counter));
counter--;
}
}
In onCreate() you're starting an infinite loop inside of the UI thread, blocking it completely. Alternatively you could use a Handler for periodic updates. Maybe using a bigger delay and stop it sometime.
public class MainActivity extends AppCompatActivity implements Runnable {
private final Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
run();
}
#Override
public void run() {
updateTv();
mHandler.postDelayed(this, 17);
}
public void updateTv() {
int counter = 100;
final TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(String.valueOf(counter));
counter--;
}
}
Anyway you should read What is the Android UiThread (UI thread) for sure.
Consider using Timer class which allows you to define a callback method that will be invoked at specified rate.
An example that fits your needs:
public class CounterActivity extends AppCompatActivity {
private TextView mCounterTextView;
private Timer mTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_counter);
mCounterTextView = (TextView) findViewById(R.id.counterTextView);
mTimer = new Timer();
mTimer.scheduleAtFixedRate(
new CounterTask(100), 0, TimeUnit.SECONDS.toMillis(1));
}
protected class CounterTask extends TimerTask {
protected int mCounter;
CounterTask(int initial) {
mCounter = initial;
}
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterTextView.setText(String.valueOf(mCounter));
}
});
--mCounter;
}
}
}
One more thing that should be noticed. As Timer executes it's own thread - it prevents you from updating your UI from outside of the main thread. In that case
you have to register a Runnable using runOnUiThread method.
Also, calling findViewById in a loop is not the best idea.
Here's my code:
public class SomeName extends MapActivity implements OnClickListener, OnTouchListener{
public Timer t1 = new Timer();
public TimerTask tt;
public long interval = 5000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.map);
timer();
}
public final void timer()
{
t1 = new Timer();
tt = new TimerTask() {
#Override
public void run() {
systemClick();
}
};
t1.scheduleAtFixedRate(tt, 10000, interval);
}
public void systemClick()
{
Toast.makeText(getApplicationContext(),"System Button Clicked", 5).show();
}
Actually, I want to call some function, where I refresh my location.
But I can't understand why I never get the toast on the screen.
I'm new to android.
Thanks for any help.
use handler in your Activity
final Handler handlerforadd = new Handler();
Runnable runnableforadd = new Runnable() {
#Override
public void run() {
handlerforadd.postDelayed(this, 1000);
}
};
handlerforadd.postDelayed(runnableforadd, 0);
The reason is the Toast has to be done on the UI thread. In your current code the method run() is being executed on a separate thread. I would suggest looking at this article on Processes and Threads. #parag is correct using a Handler is one way to get a reference to the UI thread but there are other methods.
i am trying to make facebook asynchronous non blocking thread in android. due to which our UI is run separate thread but i am unable to do that can any one tell me how to do that.
and If possible pleade give me one example.
Thanks.........
I don't know much about the Facebook but to access to the ui component from the other thread-
public class Dictionary extends Activity{
Handler mhandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Handler mhandler = new Handler();
SearchThread thread = new SearchThread();
thread.setParent(this);
thread.setHandler(mhandler);
}
public void notifyItemChanged(ArrayList<ListItem> lItems){
//write code relating to ui here
}
private class SearchThread extends Thread{
private Handler handler;
Dictionary parent;
public void setParent(Dictionary parent) {
this.parent = parent;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
#Override
public void run() {
final Runnable mUpdateResults = new Runnable() {
public void run() {
parent.notifyItemChanged(listItems);
}
};
handler.post(mUpdateResults);
}
}