I have a native method which is called from Java layer and is called
successfully.
The native method sends two integer values to the java layer at different times, and these values are received successfully in the java layer (to and fro data transfer is successful.).
My problem is:In android GUI I have take these two values and update the textbox(textview) with the data received at the java layer. The data can be seen in the log if i print it(system.out.println(..).... or Log.e(..)). but the 'textbox.settext(..) doesn't update the textbox, even though it is printed in string format.
How can i update these values in the Android GUI Layer ?
I tried using thread, handler and postinvalidate() methods, but nothing seems to work.
Can anyone tell me on how to update the gui on runtime ? Any trick to update or refresh ?
Thanks.
Sounds like you use "myTextView.setText("new");" but you are not in the ui-thread.
try
runOnUiThread(new Thread()
{
public void run()
{
//update your view here
}
});
furthermore take a look at:
Android update UI
Related
My initial question was: Android GraphView project get freeze with real time updates. In this one I was asking about possible concurrency in UI thread of 3 plots. On memory allocation plot it looks like this:
I was receiving data directly from my ProcessThread in main activity and pass it using onEventMainThread from EventBus library back to the GraphFragment. All the data that is passed comes from ProcessThread which gathers data from Bluetooth listening service and then proceeds it to get meaningful numbers.
My idea was to test if this same will happen with test thread that only generates data and sends it to onEventMainThread. Because this also produces some errors I was forced to ask another question: Difficulty in understanding complex multi threading in Android app. After some time I've received great answer from #AsifMujteba explaining that my test thread is simply too fast.
Knowing that I was able to return to my main problem and my real thread to check if all the timings are correct. As I've said there is a lot going on so being to fast is not a problem (however, I've added this same mechanize to test if data isn't send to fast). I would be more concern about to slow work of this thread.
My current onEventMainThread looks like that:
public void onEventMainThread(float[] data) {
mSeries1.appendData(new DataPoint(counter,data[0]),true,100);
mSeries1.appendData(new DataPoint(counter,data[1]),true,100);
mSeries1.appendData(new DataPoint(counter,data[2]),true,100);
counter++;
}
Unfortunately when I've returned to the beginning the problem emerged again. After a lot of testing I am able to say that data looks like is being send correctly. I've checked it with two markers:
public void onEventMainThread(float[] data) {
Log.d("LOG","marker1");
mSeries1.appendData(new DataPoint(counter,data[0]),true,100);
mSeries1.appendData(new DataPoint(counter,data[1]),true,100);
mSeries1.appendData(new DataPoint(counter,data[2]),true,100);
counter++;
Log.d("LOG","marker2");
}
Logcat messages are appearing correctly. Unfortunately the error appears even though the sending looks this same as in my test thread:
if((System.currentTimeMillis()-start)>10) {
values[0] = (float) getRandom();
values[1] = (float) getRandom();
values[2] = (float) getRandom();
EventBus.getDefault().post(values);
start = System.currentTimeMillis();
}
What's more I am sure that the data is correctly send all the time because when I've tested another fragment with OpenGL visualization everything works.
So to sum everything up:
When sending values to the fragment using EventBus from one (very simple) thread everything works great, while sending from another (more complex) thread ends in freezing of display and showed memory allocation graph. It is important to know, that if one thread is running the second one is commented out.
Can someone please advice me what might be a problem here? Or what should I check more?
EDIT
I have done one more test with commenting out everything regarding Series data append leaving only Log.d() and no error appeared. What is interesting is that the blocking (or freezing) of graph updates doesn't affect UI itself so I can still press all the buttons and so on.
Have you tried using a Custom eventbus and not the default one?
I had a similiar problem today and i fixed that by creating a custom evenbus with a seperate ThreadPool and it worked like a charm.
I am using notifications.jsm to provide notification for downloads from Downloads.jsm. The following code is incorrect in notifications.jsm :
unregisterHandler: function(key, handler) {
let i = _handlersMap[key].indexOf(handler);
if (i > -1) {
_handlersMap.splice(i, 1);
}
},
_handlersMap is an object, so splice is not a function.
Additionally, perhaps because of the unregisterHandler method being incorrect, there are occasions when having uninstalled my addon and create a new Notification in the reinstalled addon I am getting dead objects in the observe method.
My code creates a separate handler for each new notification with a handlerKey incremented by one for each new download. For the different observe event types the code is similar, the handlers for the key are iterated and the corresponding method is called. Since I have registered a different handler for each notification there should be only one handler for that key to call but this is not the case, there are dead objects from the previous addin that have the same key from the new addon. Surely this behaviour is not correct.
Please can someone look at this and the other posts that I have made regarding the firefox sdk. I only thought that Microsoft could provide undocumentation, in fact this is much worse as the documentation is nonsense and the code that is being provided has errors.
Regards
The test looks like that (it's ActivityInstrumentationTestCase2):
public void testItShowsThreeRows() {
activity = getActivity();
activity.runOnUiThread(new Runnable() {
public void run() {
AccountsList accountsList = new AccountsList(activity, accounts);
list.show();
}
});
ListView listView = (ListView)activity.findViewById(R.id.list);
assertEquals(3, listView.getChildCount());
}
The code I'm trying to test works. But the test fails because activity.runOnUiThread returns immediately. I can insert Thread.sleep and the test turns green but it looks kinda clumsy to me. Do I have to use some thread synchronization or may be poll for some UI element to be ready?
I tried to annotate it with #UiThreadTest but that doesn't work either. The code in list.show() populates a ListView via custom adapter and getView is called on another thread (not the one test runs on - and I have nothing to do with that, I have no threads or asynctasks, no nothing). The test fails again because it returns before UI is ready to be checked.
Calling waitForIdleSync() is better than sleeping for a fixed time.
You have to do a Thread.sleep. I don't think there's a way around this. I don't see why that's "clunky"; you're doing a test, so you have to wait for the system to show the UI element you want to test.
It seems to me, though, that you're really trying to test AccountsList or list. There's little reason to test ListView or findViewById unless you're paranoid.
You should focus on testing AccountsList and your custom adapter. You shouldn't have to use the UI to do this.
Following documentation, "One of the key parts of Espresso is its ability to synchronize all test actions. Espresso waits until the UI is idle before it moves to the next operation. Likewise, it waits for AsyncTask background operations to complete. In general, this should address the majority of test synchronizations in your application. If you have written UI tests before, you will appreciate this feature - there's no need to add waits or synchronization points to your app!
However, sometimes it is not possible to rely on automatic synchronisation, for instance when your app does background operations via non-standard means (managing threads directly or using custom Services). If you have run into a situation where you cannot rely on Espresso to automatically handle the synchronization for you, you can use idling resources and still rely on Espresso for synchronization."
You can read a full example at the testing codelab, you can also get the source code of the sample in github.
I have hundreds of CheckBox widgets in my layout and now I'm trying to invert each of them, so if it was checked it won't be checked and vice versa. Obviously such heavy work should be done in separate thread, but the problem is that all the work actually happens the UI. Part of the thread code:
for (int x = 0; x < list.getChildCount(); ++x)
{
final WListRowTarget curRow = (WListRowTarget)list.getChildAt(x);
curRow.post(new Runnable()
{
public void run()
{
try
{
curRow.getCheckBox().setChecked(!curRow.getCheckBox().isChecked());
}
catch (Exception e) {}
}
});
}
The only thing that this thread actually can do is looping through the list and posting the Runnable for every found checkbox. The problem is that all those Runnables arrive in the UI thread almost at the same time, thus they're all executed at once... The application behaves exactly like I would run the above code in the UI thread - everything freezes. A possible solution is sleeping for some miliseconds after each checkbox so the Runnable can be executed and the UI will have time to process the events... but it's more like a hack.
How can I solve this problem?
Thanks in advance,
Snowak
I have hundreds of CheckBox widgets in my layout and now I'm trying to invert each of them, so if it was checked it won't be checked and vice versa. Obviously such heavy work should be done in separate thread
No - this is fundamentally UI work, and frankly setting a bunch of flags isn't really "heavy" work. Most of the "work" involved is actually the UI repainting - which obviously does have to be done on the UI thread anyway. Creating lots of different tasks to execute on the UI thread is just giving it more work to do - just do the whole lot in one batch on the thread without trying to use different threads.
As a separate matter, I wouldn't want to use a UI with several hundred check boxes even on a desktop, let alone on a mobile - are you sure you shouldn't redesign your UI? You may find that coming up with a more elegant design removes any performance hit anyway...
Assuming you are using a listview to display all your checkboxes you don't need to use multiple threads. Store the state of the checkboxes in a data-structure and process everything using a single thread.
While doing the processing ( sounds so wrong :-) ) just show a spinner. You can then display all the checkboxes based on the state stored in the datastructure.
Okay, I've solved the problem myself. The solution is to use Object.wait() and Object.notify() in order to wait for the Object.post() to do the job. This way I don't post more events until the previous one is executed.
The code looks like:
synchronized (someObject)
{
someObject.post(new Runnable()
{
// some work here
synchronized (someObject){ someObject.notify(); }
});
someObject.wait(); // this line unlock the object
}
I like that my GUI appears immediately when the user starts the app.
Then some data (text, pictures) gets loaded in the background (like YouTube app).
The ListView and Gallery gets updated automatically with this new data.
I initiate my ListView, start a Thread and load the data... and then the ListView does not get updated!
Several people told me I should use notifyDataSetChanged().
But I cannot place this command in my Thread (just unknown).
Any ideas?
I have this same problem... and I got excited when I came across this question. But no answer? :-(
After, letting the problem sit for about two weeks I found the solution here:
Long story short:
Quote from above link:
We must use a Handler object because
we cannot update most UI objects while
in a separate thread. When we send a
message to the Handler it will get
saved into a queue and get executed by
the UI thread as soon as possible.
Once you check out the code you see get what the author is saying.
NOTE: Even with a handler, Android may not let you update a view object from the thread's run() method.
I got this error:
05-31 02:12:17.064: ERROR/AndroidRuntime(881):
android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
To get around it I updated an array of data in my run() method and used that array to update the view in the handler's handleMessage() method.
I hope this helps others out there.
You may use the slowAdapter to refresh the View:
SlowAdapter slowAdapter = new SlowAdapter(this);
list.setAdapter(slowAdapter);
slowAdapter.notifyDataSetChanged();
Just found it myself while reading this thread and trying around.
Short: AsyncTask's method onProgressUpdate can touch the view: http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)
Background: I needed to call requery on my cursor so a ListView kept being updated while the task fills the database. The requery call made in doInBackground failed with the mentioned CalledFromWrongThreadException but same code in onProgressUpdate works.