Android HandlerThread update UI without UiHandler - java

this code works fine and update my "TextView" and also show "Toast"
and that is my Headache as I have tried to to pass A Runnable obj Without including my UiHandler on it as it suppose to be the bridge to update my UI Thread but my activity got updated with no single Error ?????
This not suppose to be as CustomHandlerThread should be A different thread
why this happen ?
My Activity
public class TestActivity extends BaseActivity {
Runnable task;
#BindView(R.id.send_test_message)
Button send_test_message;
private Handler mUiHandler = new Handler();
private MyWorkerThread mWorkerThread;
#Override
public void initViews() {
}
#Override
public void attachViewsListeners() {
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
ButterKnife.bind(this);
task = new Runnable() { ///this is normally work I have no problem with
///that
#Override
public void run() {
mUiHandler.post(new Runnable() {
#Override
public void run() {
send_test_message.setText("Change--->1");
}
});
}
};
}
#Override
protected void onStart() {
super.onStart();
mWorkerThread = new MyWorkerThread("myWorkerThread");
mWorkerThread.start();
mWorkerThread.prepareHandler();
mWorkerThread.postTask(task);
mWorkerThread.postTask(new Runnable() { /// why this task work with no
///error ?
#Override
public void run() {
send_test_message.setText("Change--->2");
}
});
}
#Override
protected void onDestroy() {
mWorkerThread.quit();
super.onDestroy();
}
my HandlerThread
//MyWorkerThread.java
public class MyWorkerThread extends HandlerThread {
Handler mWorkerHandler;
public MyWorkerThread(String name) {
super(name);
}
public void postTask(Runnable task) {
mWorkerHandler.post(task);
}
public void prepareHandler() {
mWorkerHandler = new Handler(getLooper());
Log.e("MyWorkerThread--->",Looper.myLooper().getThread().getName()); //-->main
Log.e("MyWorkerThread--->",getLooper().getThread().getName());//-->//myWorkerThread
Log.e("MyWorkerThread--->",Thread.currentThread().getName()); //-->main
}
}
I followed this link as A Referance
is My thread running on the MainThread or getLooper() intialize my
HandlerThread with MainThread Looper ,is those log message are true
please illuminate me

After fill day of debugging i Found out That if i post A Runnable to my
mWorkerThread with sleep() as here i got " Only the original thread that created a view hierarchy can touch its views."
as should be.. but until I know why it not works without it
I wish it would help some one.
try {
TimeUnit.SECONDS.sleep(2);
send_test_message.setText("Change--->");
} catch (Exception e) {
e.printStackTrace();
}

Related

Android - change UI immediately

After click button I would like to change its color, then wait one second and change its color back.
This is my code:
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
It doesn't work. I've checked it with more complex code and debugger and it looks like all UI changes are made collectively after finish this function.
I've found this thread: apply ui changes immediately and tried to put setBackgroundColor() and setClickable() into runOnUiThread function:
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
}
});
But it also doesn't work. What should I do?
Something like this :
private final Handler handler = new Handler();
public void click(final View view) {
view.setBackgroundColor(Color.parseColor("#0000ff"));
view.setClickable(false);
handler.postDelayed(() -> {
view.setBackgroundColor(Color.parseColor("#e2e2e2"));
view.setClickable(true);
}, 1000);
}
#Override protected void onPause() {
super.onPause();
handler.removeCallbacks(null);
}
The question is not very clear. However, I am trying to summarize the question that I have understood from your question.
You are trying to set a button's background color on clicking on it and change it back after some time. If this is the situation, then I think your idea of how threads work is wanting.
In your code, the button will change the color immediately as the sleep that you are using is running in another thread (other than UI thread). The code is executed correctly, however, you cannot see the effect of the Thread.sleep as its running in a separate thread.
So all you need to do here is to change the background color again inside the thread. Modify your code like the following.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
This should work.
I have created a demo trying to show what the code will do.
However, using Handler in case of updating UI elements in this specific case is recommended. Please see the comments below.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
}, 1000);
}
Not sure why that wouldn't work, but I've done something similar with
delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//change stuff on ui
}
});
}
}, 1000);
if that doesn't work the only other functional difference in my code is that instead of btn being a final Button it's a private global variable in my activity.
Hope the following code will help :
btn.setBackgroundColor(Color.RED); // color you want for a second
new CountDownTimer(1000, 1000) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
btn.setBackgroundColor(Color.BLUE); //to change back color to prior state
}
}.start();
Try this,i think it's work for you..
final Button bPdf = findViewById(R.id.pdf);
bPdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bPdf.setBackgroundColor(Color.parseColor("#0000ff"));
new CountDownTimer(1000, 50) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
bPdf.setBackgroundColor(Color.parseColor("#e2e2e2"));
}
}.start();
}
});

Starting a thread with a button

I'm programming a small android app in Java/eclipse.
In one part of my app i need a thread, as i build in the following way:
protected void onResume() {
super.onResume();
// we're going to simulate real time with thread that append data to the graph
new Thread(new Runnable() {
#Override
public void run() {
// we add 100 new entries
for (int i = 0; i < 100; i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// sleep to slow down the add of entries
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// manage error ...
}
}
}
}).start();
}
Evertything works fine so far. But now i want to start that thread not automatically. I want to handle ".start()" with a button.
How can i realize it?
I'm very new to Java and Android.
Thanks in Advance!
You can use Handler with Runnable instead of your Thread idea, Check out the following code, it server your purpose,
private Handler broadcastHandler;
private Runnable broadcastRunnable;
protected void onResume() {
super.onResume();
broadcastRunnable = new Runnable() {
#Override
public void run() {
// Your UI related operations
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// Add some delay
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}
}
public void onButtonClick(View view) {
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}

AsyncTask data communication with nested Classes

I have a specific scenario and I need your help.
I'm trying to build an App in Android that involves network communication.
I am using AsyncTask for the http POST requests.
I have another class called Proxy (not a good one.. will be changed) which holds different kinds of functionalities (registerUser, setUserName, getUserPermission...)
And Of course, I have an Activity.
My Activity holds an instance of Proxy class.
My goal, is to push a button in the activity, it will call a method from Proxy class, which in its turn calls the AsyncTask's execute() method that actually run the http POST.
I was wondering how to get the data from AsyncTask's onPostExecute to my activity.
What I have in mind is to have an interface in AsyncTask, which will be implemented in Proxy class, and another interface in Proxy class which will be implemented in my Activity class.
Roll the data all the way to my Activity.
I want to hear your thoughts about whether this is the way to go, or another approach is preffered.
Thanks a lot for your help.
Adding some code
public class RegisterActivity extends FragmentActivity implements Proxy.OnProxyHttpPostResponseListener {
private Proxy proxy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
this.proxy = new Proxy();
this.proxy.setHttpPostResponseListener(this);
}
#Override
public void onProxyHttpPostResponse(String response) {
//Do something when http post returns
}
}
public class Proxy {
public interface OnProxyHttpPostResponseListener {
void onProxyHttpPostResponse(String response);
}
private OnProxyHttpPostResponseListener httpPostResponseListener;
public void setHttpPostResponseListener(OnProxyHttpPostResponseListener listener) {
this.httpPostResponseListener = listener;
}
private class HttpPostAsync extends AsyncTask<Pair<String, ArrayList<Pair<String, String>>>, Void, String> {
#Override
protected String doInBackground(Pair<String, ArrayList<Pair<String, String>>>... params) {
return this.httpPost(params[0].first, params[0].second);
}
protected void onPostExecute(String response) {
httpPostResponseListener.onProxyHttpPostResponse(response);
}
}
If you're just needing HTTP POST functionality then an AsyncTask might not be the best choice. AsyncTask really shines if you need to get progress updates as the task is executing (with onProgressUpdate(Progress... progress)). If you'd like to use AsyncTask nonetheless, iroiroys' reply should help.
A bit more simply, you could just use a Handler thread straight up. Something like this:
public class HandlerExampleActivity extends Activity {
private Button postButton;
private Button getButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_example);
backgroundThread = new BackgroundThread();
backgroundThread.start();
postButton = (Button) findViewById(R.id.button_post);
postbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.post("DATA_HERE");
}
});
getButton = (Button) findViewById(R.id.button_get);
getbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.get("URL_HERE");
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
backgroundThread.exit();
}
private class BackgroundThread extends Thread {
private Handler backgroundHandler;
public void run() {
Looper.prepare();
backgroundHandler = new Handler();
Looper.loop();
}
public void post(DataType data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// pull data and do the POST
uiMsg = uiHandler.obtainMessage(POST_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void get(URL data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// GET data
uiMsg = uiHandler.obtainMessage(GET_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void exit() {
backgroundHandler.getLooper().quit();
}
}
private final Handler uiHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case POST_COMPLETE:
// handle it
break;
case GET_COMPLETE:
// handle it
break
case MESSAGE_BACK_TO_UI_THREAD:
// do something
break;
case OPERATION_FAIL:
// oh no!
break;
case OPERATION_SUCCESS:
// yay!
break;
}
}
};
}
I suggest you try Handler and Handler.Callback.
Below I made it simple example..
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
public class MainActivity extends Activity implements Callback {
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler(this);
Proxy proxy = new Proxy(handler);
proxy.foo();
}
private class Proxy {
Handler handler;
public Proxy(Handler handler) {
this.handler = handler;
}
private void foo() {
new myAsync().execute();
}
private class myAsync extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Message msg = handler.obtainMessage();
msg.obj = result;
handler.sendMessage(msg);
}
}
}
#Override
public boolean handleMessage(Message msg) {
// Handle Message here!
return false;
}
}

Is it possible to perform separate network thread within a same activity without wait?

I am performing two class which is extending ASyncTask and both have different functions but because of the second class my first class is lagging. So what i want to know is, is there any better solution to code in such a way that both of the operation will perform the task without making other operation to wait?
Updated with code
For the first call in the onCreate()
new connection().execute(); //
Some task performed by the same class called
public class connection extends AsyncTask {
#Override
protected Object doInBackground(Object... arg0) {
//some operation
return value;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
String m = String.valueOf(o);
if (o != null) {
someoperation
} else {
edittxt.setTextColor(Color.RED);
edittxt.setText("No Internet Connection");
}
}
}
similarly i am performing the other class that i have.
You can use AsyncTask.executeOnExecutor with THREAD_POOL_EXECUTOR, the default executor is SERIAL_EXECUTOR.
You can create two separate threads and perform your operations. It will quarantine, that all operations will be performed async.
final Handler handler = new Handler();
Thread operation1 = new Thread(new Runnable() {
#Override
public void run() {
doOperation1();
handler.run(new Runnable(){
#Override
public void run() {
onPostExecute1();
}
});
}
});
Thread operation2 = new Thread(new Runnable() {
#Override
public void run() {
doOperation2();
handler.run(new Runnable(){
#Override
public void run() {
onPostExecute2();
}
});
}
});
operation1.start();
operation2.start();

Calling Method w/ Argument on Main Thread from Secondary Thread

Like the title suggest I have an android project with a MainActivity class that has a TextView that I want to set the text of after receiving a message. I also have a class that runs a ServerSocket on a separate thread that receives the string message I want to display.
Part of my MainActivity looks like this,
private Handler UIHandler = new Handler();
private RemoteControlServer remoteConnection;
public static final int controlPort = 9090;
public class MainActivity extends Activity implements SensorEventListener
{
...
remoteConnection = new RemoteControlServer(controlPort, UIHandler);
...
private class RemoteControlServer extends RemoteControl
{
RemoteControlServer(int port, Handler ui)
{
super(port, ui);
}
#Override
public void onReceive(String[] msg)
{
//updates messages textview
}
#Override
public void onNotify(String[] msg)
{
//updates notification textview
}
}
}
The RemoteControlServer implementation of code that calls the onReceive(String[] msg) and also handles receiving messages on the different thread looks like this,
...
public abstract void onReceive(String[] msg);
public abstract void onNotify(String[] msg);
...
controlListener = new Thread(new Runnable()
{
boolean running = true;
public void run()
{
String line = null;
while(running)
{
try
{
//Handle incoming messages
...
onReceive(messages);
}
catch (final Exception e)
{
UIHandler.post(new Runnable()
{
public void run()
{
onNotify("Wifi Receive Failed " + e.toString() + "\n");
}
});
}
}
}
});
...
I'm getting the error "Only the original thread that created a view hierarchy can touch its views." when onReceive() is called and throws the exception and calls onNotify() with the exception description. Why does the onNotify() work but the otherone does not? How can I correctly call the listener to the the TextView and update its text? Thanks
private class RemoteControlServer extends RemoteControl
{
...
public class BridgeThread implements Runnable
{
String[] msgArray = null;
public BridgeThread(String[] msg)
{
msgArray = msg;
}
public void run()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
TextView zValue = (TextView) findViewById(R.id.connectionStatus);
zValue.setText(msgArray[0]);
}
});
}
}
#Override
public void onReceive(String[] msg)
{
BridgeThread bridgeTest = new BridgeThread(msg);
bridgeTest.run();
}
...
}

Categories

Resources