Can someone help me to correct my code.
(https://i.stack.imgur.com/jKOvH.png)
I am trying to display realtime Count from 0 to 10 and displaying that on textView but always crash. Iam new on android but Very excited to learn.please help me explain that problem. Sorry for my bad English.
Well, i'm not an Android developer myself but from what i understood online, what you did is to create a Handler and provide Looperassociated with the main thread. This associate this handler to the main thread. When we post the Runnable, it gets queued in the main thread’s MessageQueue and then executed in the main thread.
Creating an own thread and providing Lopper and MessageQueue is not the right way to deal with the problem. So, Android has provided HandlerThread(subclass of Thread) to streamline the process. Internally it does the same things that we have done but in a robust way. So, always use HandlerThread.
private class MyHandlerThread extends HandlerThread {
Handler handler;
public MyHandlerThread(String name)
{
super(name);
}
#Override
protected void onLooperPrepared() {
handler = new Handler(getLooper()) {
#Override
public void handleMessage(Message msg) {
// process incoming messages here
// this will run in non-ui/background thread
}
};
}
}
Information found at: https://blog.mindorks.com/android-core-looper-handler-and-handlerthread-bd54d69fe91a
Try this code to create new thread under activity. there is no need to create handler.
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
text.setText(value);
}
}
};
new Thread(runnable).start();
just :
new Handler().post(new Runnable() {
#Override
public void run() {
...
}
});
you can try it.
Related
when I use exoplayer I get a player is accessed on the wrong thread error. How can I solve this?
Non-fatal Exception: java.lang.IllegalStateException: Player is accessed on the wrong
thread.
Current thread: 'main'
Expected thread: 'ConnectivityThread'
See https://exoplayer.dev/issues/player-accessed-on-wrong-thread
The player is started as a service via my BackgroundAudioService.class.
exoPlayer = new ExoPlayer.Builder(getApplicationContext()
.build();
In the main thread my looper is running, the
which updates the UI via exoplayer.getCurrentPosition().
public final Runnable updatePosition = new Runnable() {
#Override
public void run() {
position = BackgroundAudioService.getCurrentPostion();
}
}
myHandler.postDelayed(updatePosition, myHandlerSleep);
I don't know how to solve this problem (which occurs just sometimes), please help.
Thanks
Alejandro
I solved this by calling the status via a handler in the player's event listener. Starting a runnable from the listener which runs only when player.isPlaying() == true.
player.addListener(new Player.Listener() {
#Override
public void onEvents(Player player, Player.Events events) {
Player.Listener.super.onEvents(player, events);
if (events.contains(Player.EVENT_IS_PLAYING_CHANGED)) {
if (player.isPlaying()) {
positionHandler.postDelayed(getCurrentPositionTask,CURRENT_POSITION_SLEEP);
} else {
positionHandler.removeCallbacks(getCurrentPositionTask);
}
}
}
});
public Runnable getCurrentPositionTask = new Runnable() {
#Override
public void run() {
if (exoPlayer != null) {
currentPostion = exoPlayer.getCurrentPosition();
positionHandler.postDelayed(getCurrentPositionTask,CURRENT_POSITION_SLEEP);
}
}
};
The UI calls the current position the same way in a runnable.
I can't say whether this is the best way. but it's going well.
GGK
I have AsyncTask class with methods like this(class: ApiConnector):
#Override
protected String doInBackground(Void... voids)
{
return getToken(); //<-- do many the most important things and return String
}
and
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
}
and then in my Activity:
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here: ", result);
}
}.execute();
It work's fine when I execute this one time, but i have to do this in endless loop to take always fresh token like fresh apples in my market. I tried something like that:
while (true)
{
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here!", result);
}
}.execute();
Thread.sleep(1000);
}
and many many stupid things, but i can't find working way. All thread bussiness is tricky for me. Give me some kick and I manage this for sure.
You don't want to do this. All AsyncTasks run on one thread. If you infinitely loop inside an AsyncTask, you'll starve all other tasks. If you have each task start a new task, then you'll still risk major starvation issues.
If you want to do this (and I'm not sure you really do, but lets ignore that), the correct way is to use a Thread. A Thread can just have a giant while(true) loop and a sleep statement at the end.
Like hrskrs commented I would prefer using a Handler to execute something repeatedly. The main advantage is that postDelayed makes the run() method execute in the main application thread - so you can access and change UI components.
Here's an example:
public class MyTest implements Runnable {
private final static int INTERVAL = 5000;
private Handler mHandler;
private MyTest() {
mHandler = new Handler();
}
public void start() {
run();
}
public void stop() {
mHandler.removeCallbacks(this);
}
#Override
public void run() {
// put here the logic that you want to be executed
mHandler.postDelayed(this, INTERVAL);
}
}
I have a handler for a thread in my MainActivity that calls a method named UpdateGUI.
Both the handler/thread declaration and the method are within the MainActivity.
This is the handler Declaration:
Handler handlerData = new Handler();
private Runnable runnableCode2 = new Runnable() {
#Override
public void run() {
Log.d("Handlers","GET TOTAL RX BYTES: "+Long.toString(res) );
//Some code here that doesn't matter/
UpdateGUI();
}
handlerData.postDelayed(runnableCode2, 1*6000);
}
};
And UpdateGUI is as follows:
public void UpdateGUI(){
Log.d("Updater", "STARTING UPDATE");
//Code that doesn't matter here}
}
From the logger I can see that UpdateGUI() is not being called from the thread. Can you explain why this is happening and how it can be fixed?
Just to clarify. The thread is running,but for some reason it doesn't make the call to UpdateGUI().
You need to atleast run handler once then only it will continuously called from the handler runnable method.
so call handler.post(runnableCode2); once in your code and that will be repeated
handlerData.postDelayed(runnableCode2, 1*6000);
hope this will resolved your issue.
I cant see you starting the Runnable.
Handler handlerData = new Handler();
private Runnable runnableCode2 = new Runnable() {
#Override
public void run() {
Log.d("Handlers","GET TOTAL RX BYTES: "+Long.toString(res) );
//Some code here that doesn't matter/
UpdateGUI();
}
handlerData.postDelayed(runnableCode2, 1*6000);
}
};
// This part is missing
handlerData.postDelayed(runnableCode2, 1000);
In the last days I have found myself using this approach for asynchronously performing some long operation (several seconds), and then return some value via a callback that must execute on the caller thread, which is typically but not necessarily the UI thread.
public abstract class DoSomethingCallback
{
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback)
{
// Instantiate a handler for the calling thread
final Handler handler = new Handler();
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(clearBytes);
}
});
}
}).start();
}
This seems to work pretty well and is very simple to use. However, I somehow suspect it might have some problems I'm not aware of. So the question is, what are the potential issues of this approach? What are better alternatives than manually creating and running a thread? I'm seeking for simplicity and robustness.
The only problem is that such approach breaks encapsulation: the second thread not only computes the result, but also dictates what the caller thread should do with it. So I'd better refactor your code as follows:
public abstract class DoSomethingCallback {
final Handler handler = new Handler();
public void post(final Object result) {
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(result);
}
});
}
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback) {
// Instantiate a handler for the calling thread
final DoSomethingCallback handler = new DoSomethingCallback () {
void done(Object result) {
...
}
};
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(result);
});
}
}).start();
}
I have a for loop which calls a function to download a file.
Each time the function is called the title of the file is displayed in a TextView.
The problem is the files are downloaded but the UI freezes up, and it is only after the files have finished downloading that the UI is updated, and only the last title for the last file is shown.
for(int i=0; i < Titles.size(); i++){
downloading.setText("Downloading: "+Titles.get(i));
if(!Utils.downloadFile(Mp3s.get(i))){
downloading.setText("ERROR Downloading: "+Titles.get(i));
}
}
I know I have to use a Handler or Thread to sort this issue out.
But I am not sure how to implement it.
You could try using Activity.runOnUiThread() - something like:
// Move download logic to separate thread, to avoid freezing UI.
new Thread(new Runnable() {
#Override
public void run() {
for(int i=0; i < Titles.size(); i++) {
// Those need to be final in order to be used inside
// Runnables below.
final String title = Titles.get(i);
// When in need to update UI, wrap it in Runnable and
// pass to runOnUiThread().
runOnUiThread(new Runnable() {
#Override
public void run() {
downloading.setText("Downloading: "+title);
}
});
if(!Utils.downloadFile(Mp3s.get(i))) {
runOnUiThread(new Runnable() {
#Override
public void run() {
downloading.setText("ERROR Downloading: "+title);
}
});
}
}
}).start();
That's pretty verbose (yeah, Java!) and, in my opinion, not very readable.
Another solution would be to use AsyncTask, which has convienient onProgressUpdate() method designed to update UI for a long-running task. It could look like:
public class DownloadTask extends AsyncTask<URL, String, Void> {
// This method will be run off the UI thread, no need to
// create separate thread explicitely.
protected Long doInBackground(URL... titles) {
for(int i=0; i < titles.length; i++) {
publishProgress("Downloading " + titles[i]);
if(!Utils.downloadFile(Mp3s.get(i))) {
publishProgress("ERROR Downloading: " + titles[i]);
}
}
}
// This method will be called on the UI thread, so
// there's no need to call `runOnUiThread()` or use handlers.
protected void onProgressUpdate(String... progress) {
downloading.setText(progress[0]);
}
}
(please note that code above is hand-written not-compiled, so it's probably buggy, but it should give you an idea how to go from here.