I need to update ui from runnable. My logic goes like below.
I start the runnable from onCreate of the fragment lifecycle. And the runnable instance is responsible to request network. The problem is I don`t know how to update the fragment after runnable instance fetched the data from network.
code to start runnable in fragment in CustomFragment.java.
public void onCreate(Bundle savedInstanceState) {
Log.d(DEBUG_TAG, "onCreate");
super.onCreate(savedInstanceState);
accountMgr.requestAccountInfo();
}
code to start runnable in AccountManager.java
/**
* request Account info from server
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void requestAccountInfo() {
Account act = getCurrentAccount();
Thread t = new Thread(new RequestAccountInfoTask(act));
t.start();
}
/**
* automatically update Account info, like space usage, total space size, from background.
*/
class RequestAccountInfoTask implements Runnable {
private Account account;
public RequestAccountInfoTask(Account account) {
this.account = account;
}
#Override
public void run() {
doRequestAccountInfo(account);
}
}
runOnUiThread() requires Activity reference. There are alternatives. You don't need Activity reference to your Thread. You can always get UI handler with the main looper. Pass other arguments like your interface to update the fragment upon completion of your task.
class RequestAccountInfoTask implements Runnable {
private Account account;
private Handler mHandler;
public RequestAccountInfoTask(Account account) {
this.account = account;
mHandler = new Handler(Looper.getMainLooper());
}
#Override
public void run() {
doRequestAccountInfo(account);
//use the handler
}
}
Anything you run on the instantiated Handler will be on UI thread.
Of course, using runOnUiThread() is totally reasonable.
you can use runOnUIThread method of activity.
here's code may be help you:
class RequestAccountInfoTask implements Runnable {
private Account account;
public RequestAccountInfoTask(Account account) {
this.account = account;
}
#Override
public void run() {
doRequestAccountInfo(account);
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// you can update fragment UI at here
}
});
}
}
}
Please take a look at AsyncTask for updating the UI from a thread:
http://developer.android.com/reference/android/os/AsyncTask.html
Here are the highlights from the above link:
Class Overview AsyncTask enables proper and easy use of the UI thread.
This class allows to perform background operations and publish results
on the UI thread without having to manipulate threads and/or handlers.
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.
An asynchronous task is defined by a computation that runs on a
background thread and whose result is published on the UI thread. An
asynchronous task is defined by 3 generic types, called Params,
Progress and Result, and 4 steps, called onPreExecute, doInBackground,
onProgressUpdate and onPostExecute.
You Cannot Update UI from runnable. You Need Handler for Updating UI. See this for more info.
The UI only can be modified by the thread that create it. In tho most cases is by the UI thread. So you need yo update using runOnUiThread method. Good Luck
I recommend using an AsynTask or you can just try this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getActivity(), "ON UI Thread", Toast.LENGTH_LONG).show();
}
});
I know it's a bit different answer. But I want you to see Android Annotations. Which are very easy to use . I use them only for background and Ui thread. Do every task in background thread by writing #Background over your method name. And do all the UI update in UI thread. I advice you to just check it once. http://androidannotations.org/
Thanks
And as far as your answer is concern . You can not update your UI from runnable. See the asyn task for updating your Ui.
You can use the event bus to do it - http://square.github.io/otto/
It is pretty simple. Just send event from your Thread when you need to update the UI like this:
...
//in the end of your heavy job:
bus.post(new YourEvent());
and in your Activity create method:
#Subscribe
public void onYourEvent(YourEvent event) {
//do what you want there
}
by the way, you can pass any data through event, it is your custom class! Please read manual how to set up this lib, register activity for bus. It is very useful and easy-to-use
You can create a Runnable that then posts to the main thread. From Google's developer pages on Processes and Threads
This implementation is thread-safe: the background operation is done
from a separate thread while the ImageView is always manipulated from
the UI thread.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
final Bitmap bitmap =
processBitMap("image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
Related
I'm trying to connect to a PC server (using Hercules) through TCP from an android app (client) but I'm really lost and don't know where to go. None of the tutorials are fully working for me, most of them can allow me to send messages from client to server but not vice versa.
I read about connections not supposed to be run from the "main thread" but what does that mean?
Also any examples of a TCP connection from android would be great.
Thanks!
I suspect that the "main thread" in this context means that thread that is managing the user interface. If you do anything much in this thread, you run the risk of Android killing your app because it appears to have hung.
Personally, I don't think it's a huge problem to have the user interface thread block for a few milliseconds to do a TCP operation. You'd need to make sure that you code the operation to have sensible timeouts, so you don't end with a dead app because the remote server takes too long to respond.
The official way to handle situations like this is to define the network operations in services, or in separate threads, and have the user interface thread communicate with those services or threads using short-lived operations.
This process is documented with examples here:
https://developer.android.com/training/basics/network-ops/connecting
Main thread in android is responsible to create and display UI on screen
to perform task related to connection strictly need to use background thread otherwise UI become laggy.
There are two method available to perform background Task
Runnable:
new Thread(new Runnable() {
public void run() {
..... // code here
}
}).start();
Android AsyncTask: https://developer.android.com/reference/android/os/AsyncTask
Like #Kevin Boone said, Main thread means UI thread in Android.
You can't do networking operations in the Main thread, otherwise you will get NetworkOnMainThreadException. You can create a new thread and then pass result back to the Main thread using Handler. Code could look like this:
public class MyActivity extends AppCompatActivity implements FetchDataUseCase.Listener {
private FetchDataUseCase fetchDataUseCase;
private TextView textView;
private Button dataButton;
public void onCreate() {
textView = findViewById(R.id.textView);
dataButton = findViewById(R.id.dataButton);
dataButton.setOnClickListener(v -> getDataFromNetwork());
fetchDataUseCase = new FetchDataUseCase(this);
}
void getDataFromNetwork() {
fetchDataUseCase.fetchDataAndNotify();
// start async operation! and receive result in onDataFetched()
}
#Override
public void onDataFetched(String data) {
// now you are in Main thread
// do something with data
textView.setText(data);
textView.setVisibility(View.VISIBLE);
}
#Override
public void onError() {
textView.setText("ERROR!!!");
textView.setVisibility(View.VISIBLE);
}
}
public class FetchDataUseCase {
public interface Listener {
void onDataFetched(String data);
void onError();
}
private final Listener listener;
private final Handler handler = new Handler(Looper.getMainLooper());
public FetchDataUseCase(Listener listener) {
this.listener = listener;
}
public void fetchDataAndNotify() {
new Thread(() -> {
String myData = "";
try {
// your networking operation
// where you receive some data
} catch (Exception e) {
handler.post(() -> listener.onError();
} finally {
// close stream, file, ...
}
// pass it back to Listener in Ui Thread
handler.post(() -> listener.onDataFetched(myData);
}).start();
}
}
read ThreadPoster: Multi-Threading in Android
And don't use AsyncTask =)) Async task is deprecated
Also, you need to add permision to your AndroidManifest file.
<uses-permission android:name="android.permission.INTERNET"/>
Hope it will help you)) Good luck!
Is there any way to call an activity from something that doesnt extend Activity? without running it on UI-tread. I want toast-messages in my game, like in candy crush. But I have no idea how to call the toast-activity in an efficient way during real-time.
I know you can use context and get activity from that but it does not run very smoothly. Does anyone have experience with how to do this?
Toasts as well as other components that manipulates the user interface must not be used outside of the UI thread.
What you could do in order to solve your issue, is to design a messaging system between the thread managing you game, and your UI thread. In order to do so, you can use a Handler and its messaging facilities (sendMessage, post, postDelayed ...) to send messages or even Runnables to be run on your main thread.
If you create a Handler in the main thread, it will automatically associate itself with your main thread's event loop, thus making every work sent to it be executed in the main thread.
A basic example of what you could do would be :
class MainActivity extends Activity {
// The handler is associated with your Activity's thread
private Handler _handler = new Handler();
// ...
private Thread _worker = new Thread() {
#Override
public void run() {
_handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Some text", Toast.LENGTH_SHORT).show();
}
});
}
};
};
As a shorthand, you could also use Activity.runOnUiThread(Runnable r) that executes the given runnable in the UI thread by default.
in my mainActivity, which is the sole activity of my application, I am creating the below handler and running a runnable inside it.
I have some misunderstandings about handlers and where they run.
See the code
Handler handler;
#Override
protected void onCreate(Bundle bundle)
{
handler = new Handler();
handler.postDelayed(r , 5000);
}
Runnable r = new Runnable()
{
#Override
public void run() {
FetchServerAndUpdateStatus(); //network stuff in here
handler.postDelayed(r , 5000);
}
}
I assume this code will still run in UI thread and I won't be able to make any network calls in there no ?
If yes, what shall I do ? Create and use a seperate thread ?
If I created a new thread, How can I run the postdelayed method ? The thread does not have post delayed ?
Does not using handler/runnable and using TimerTask and Runnable instead a better approach ? Or, just like the above handler/runnable, that will also run on the UI thread, unless created inside a seperate one.
When you construct a Handler it is bound to the thread it is constructed on.
onCreate() is run on the UI thread so this handler will be bound to the Looper on the main thread, and thus will run on that thread.
If you want a handler you can use on another thread you can construct one.
See the looper docs: https://developer.android.com/reference/android/os/Looper.html
Which has this block:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
synchronized (this) {
this.notifyAll();
}
Looper.loop();
}
}
Add this class and then in your onCreate do the following:
mLooperThread = new LooperThread();
mLooperThread.start();
synchronized (mLooperThread) {
while (null == mLooperThread.mHandler) {
mLooperThread.wait();
}
}
mLooperThread.mHandler.postDelayed(r , 5000);
This will cause the runnable to be run NOT on the UI thread, which is probably what you wanted.
For tasks that need to interact with the UI an AsyncTask may be better since it includes a mechanism to run things that touch Views when the task is done on the UI thread, since anything that touches a View must be done on the UI thread.
The other mechanisms for executing on the UI thread are to post to the view itself:
https://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)
or
[https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long)](https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long))
Or to ask the Activity to run it on the UI for you:
https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
It depends on what you do with your handler, you didn't show, how you want to obtain m_handler. If you create it with new Handler(Looper.getMainLooper()), it will run on UI thread.
If you want to run code in background (network operations) you should use AsyncTask
I'm developing an android application, and I have a button which starts/pauses certain simulation process. While this process is running, I need to output some data from it real-time. But when I create a new thread for the simulation, I can't access views (let it be TextView) from this thread, because they only can be accessed from the thread where they were created. On the other hand, new thread is necessary because otherwise user wouldn't be able to do anything while simulation is running (for example, press some other buttons). Creating a new service also requires creating a new thread in this case. How should I solve this problem?
You can handle it in many ways,
Try to use AsyncTask in this, your background work done in doInBackGround() method, and your UI will not block and you can also access the views of Activity from where you call AsyncTask by its context via publishProgress() and onProgressUpdate() .
If you are using a simple Thread then using Handler or message or runOnUiThread you can update the view of main thread.
but, in your way I think AsyncTask is best for you.
You can solve the problem with android.os.Handler. Handler instance is bound to the thread that creates it, you can post Runnables to it and it will execute them in the thread it is bound to. For example:
import android.os.Handler;
import android.widget.TextView;
public class MyActivity extends Activity {
private Handler uiHandler;
private TextView simulationStatus;
#Override
public void onCreate(Bundle savedInstanceState) {
...
uiHandler = new Handler();
...
simulationStatus = (TextView) findViewById(R.id.simulationStatus);
...
}
// This method is to be executed on the simulation thread.
public void simulate() {
...
final String simulationStatusText = ...;
...
uiHandler.post(new Runnable() {
#Override
public void run() {
// This is run on the UI thread.
simulationStatus.setText(simulationStatusText);
...
}
});
}
...
}
You can also use AsyncTask. See the link for example.
They can be accessed but only read-only. What you mean is you want to trigger changes from a thread on the views. From the worker thread (non-UI) these changes cannot be triggered, you need to use .runOnUiThread() or use Handlers. Use these at the point where you want to show something, e.g update the textview in .runOnUiThread(),
Example:
myThread = new Thread()
{
#Override
public void run() {
//yourOperation
MyActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
if(e!=null)
{
myTextView.setText("something");
}
}});
super.run();
}
};
myThread.start();
Pass the activity to your thread, and use it from within to access your views.
// from your activity:
myExternalThread = new MyCustomCode(this); // <-- activity passed
// your "simulation process" constructor:
public MyCustomCode(Activity parent) {
this.parent = parent;
}
// and when you want to access views:
parent.runOnUiThread(new Runnable() {
#Override
public void run() {
parent.findViewById(R.id.text_view);
... do something to your UI ...
}
});
My preferred way of creating these external tasks is to use AsyncTask (then you don't have to worry about runOnUiThread, among other benefits). I don't know if it applies to your case, but you should check it out.
you have to store the data which you are wanting do show into a public var and let your Thread call a Runnable via Handler.post(runnable)
The code in the run() method of the Runnable is able to access the Textview
I am having a problem with modifying EditText in another function started by the thread:
Thread thRead = new Thread( new Runnable(){
public void run(){
EditText _txtArea = (EditText) findViewById(R.id.txtArea);
startReading(_txtArea);
}
});
my function is as follows:
public void startReading(EditText _txtArea){
_txtArea.setText("Changed");
}
It always force closes while trying to modify the edittext. Does someone know why?
UI views should not be modified from non-UI thread. The only thread that can touch UI views is the "main" or "UI" thread, the one that calls onCreate(), onStop() and other similar component lifecycle function.
So, whenever your application tries to modify UI Views from non-UI thread, Android throws an early exception to warn you that this is not allowed. That's because UI is not thread-safe, and such an early warning is actually a great feature.
UPDATE:
You can use Activity.runOnUiThread() to update UI. Or use AsyncTask. But since in your case you need to continuously read data from Bluetooth, AsyncTask should not be used.
Here is an example for runOnUiThread():
runOnUiThread(new Runnable() {
#Override
public void run() {
//this will run on UI thread, so its safe to modify UI views.
_txtArea.setText("Changed");
}
});
First of all take a look at your log, it usually contains a stack trace when an app shuts down.
You shouldn't run the thread like you normally do, instead use runOnUiThread:
Runnable thRead = new Runnable(){
public void run() {
EditText _txtArea = (EditText) findViewById(R.id.txtArea);
startReading(_txtArea);
}
};
runOnUiThread(thRead);
The explaination: Only the UI thread is allowed to change the state of UI components.
This article may help you.
http://android-developers.blogspot.com/2009/05/painless-threading.html
There are few options:
1. run it on UI thread Activity.runOnUiThread(Runnable)
2. use AsyncTask
Except runOnUiThread() (which works), there is also another way, which I know of:
Define a handler in your UI (Activity) class:
public class MainActivity extends Activity {
.....
Handler uiThreadHandler = new Handler() {
public void handleMessage(Message msg) {
Object o = msg.obj;
if (o==null) o = "";
TextView textIn = (TextView)findViewById(R.id.textin);
textIn.setText(o.toString());
}
};
}
and from inside some thread you can call it:
Message msg = uiThreadHandler.obtainMessage();
msg.obj = "Text for EditView";
uiThreadHandler.sendMessage(msg);
By default, the main thread is the UI thread. All code that modifies the appearance of the application needs to be run in this thread. If you want to have multiple threads in your application that can modify the UI I would suggest using the AsyncTask class.
public someMethod(){
new ChangeTextTask().execute();
}
private class ChangeTextTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
startReading(_txtArea);
return null;
}
}
However, you need to take steps to prevent multiple threads from accessing the EditText object at once. Otherwise you'll wind up getting a CurrentModificationException error.
http://developer.android.com/reference/android/os/AsyncTask.html