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
}
Related
Since I am new to android programming, I am not sure how to write code efficiently hence the reason for this question. I am creating an app. A basic app in which the app generates 10 random math questions and evaluates it from left to right (ignoring orders of operations). E.g. 3+5/2 should equal 4 instead of 5.5.
I am getting the error Launch timeout has expired. I have researched this and found out that its because the main thread is doing too much work. How do I overcome this? My app first does alot randomizing integers, could that be the case?
This is the code. It is pretty long.
P.S. in the display method, i hrdcoded it to display the first elements just to see if it will display.
public void initAnswers(String[] questionToBeLooped){
for(int i =0; i < questionToBeLooped.length; i++){
if(mathOperations.length == 2){
runningTotal = evaluateAnswerTwoOperations(mathOperations[0], mathNumbersInIntFormat.get(0), mathNumbersInIntFormat.get(1));
}else{
int operationsCounter =0;
int numbersCounter =1;
runningTotal = mathNumbersInIntFormat.get(0);
while(mathOperations[operationsCounter] != "="){
runningTotal = evaluateAnswerTwoOperations(mathOperations[0],runningTotal,mathNumbersInIntFormat.get(numbersCounter));
}
}
answers[i] = runningTotal;
}
}
Could someone tell me how to write this efficiently and also can you provide some tips to generate fluent and efficient apps.
Not sure what in your code is the cause, but you should offload the heavy work into an AsyncTask. AsyncTask will allow you to execute code in a background thread via doInBackground and callback to the UI thread via onPostExecute. The heavy work you are doing is probably something around the looping constructs you have.
Keep in mind that you cannot modify the UI from the background, so if you need to update UI, wait until the heavy work is finished and do it in onPostExecute.
See the docs here on AsyncTask.
Also worth noting that AsyncTask has a lot of flaws, but since you are new - it is where I would recommend to start.
I have a game loop which is constantly being called to update the game. Inside that loop is the following code:
mySurfaceView.post(new Runnable() {
public void run() {
myView.setTranslationX(myCam.getX());
myView.setTranslationY(myCam.getY());
}
});
I've been told that putting the "new" keyword in my game loops is usually not a good idea because memory is constantly being allocated to new objects. However this is an anonymous inner class so I'm not sure if the same applies here. Would this code cause performance issues? And if so, then how would I go about solving them? I use this code to make my the screen be oriented around my player when he moves.
One approach would be to send a message to a Handler on the UI thread, rather than posting a Runnable. This is easiest if your translation X/Y values are integers.
For an example, see the way ActivityHandler is used in the "record GL app" activity in Grafika. The UI thread creates a new Handler and passes it to the renderer thread, which sends messages to it. handleUpdateFps() is a good example, as it's passing a pair of integers to the UI thread.
If you can't pass the values as fixed-point, you have to pass them through an Object, and things start to get complicated. Overall this approach is more involved than simply posting a Runnable.
(A better approach would be to adjust your coordinates internally, having a notion of "world space" vs. "screen space", and not mess with the View's values. But looking at your other questions, you tried that approach and were not successful.)
So I have this view that moves throughout different views that I have. I tried moving it using a new thread but I got "Can't access View from a different thread than it was created on", so I was like, "whatever just move it to the main thread then". So, I currently have runOnUiThread(this) (The class implements Runnable).
Now, it says:
Skipped x frames! The application may be doing too much work on its main thread.
I googled for a loophole and found that I can use a Handler to do this, which I was able to follow until it was talking about implementing a task. They used a task called PhotoTask and not knowing what it was or where it came from, I just got lost.
So can somebody either explain the Task or tell me another potential way around this?
Code that's causing the error (Note there are more if statements, but they're all the same on the inside as this one:
while (lackees[i].getTileX() < lackees[i].getDestX()
&& lackees[i].getTileY() < lackees[i]
.getDestY()) {
lackees[i].setTileX(lackees[i].getTileX() + 1);
lackees[i].setTileY(lackees[i].getTileY() + 1);
getTileAt(0, lackees[i].getTileX() - 1,
lackees[i].getTileY() - 1).removeView(
lackees[i]);
getTileAt(0, lackees[i].getTileX(),
lackees[i].getTileY()).addView(lackees[i]);
Progress Update #1:
It seems that wait() is better to use then Thread.sleep() but I still get frames lost, just not as many.
Your question is not very clear.
What do you mean by "So I have this view that moves throughout different views that I have".
Handler are mainly used to communicate between 2 threads.
PhotoTask in given link is simply an object/model used to send message from 1 thread to another via Handler.
If you want to update a view, you need to do this in main/UI thread alone. If you want to do some UI update from a separate thread you need to inform the default UI thread handler by passing the operation to be done as a separate runnable instance via runOnUiThread/ view.post/ handler.post.
I can clarify on how to use shared views without using any handler or thread if this is what you need.
I'm getting data from a server for my app. The "getData" functions are included in the app's main Activity, in a splash thread. The problem I'm having is this:
If I quickly enter news or description after loading up the app, I notice that not all info has loaded (last 2 or 3 strings that needed to be saved are null). If, however, I allow the app a few more seconds after displaying the main menu (after completing the splash thread), the problem doesn't occur, all info is stored correctly on the phone. I tried delaying the splash screen by a few seconds but that's not really an elegant solution nor does it always work.
My question is how can I make sure that the functions have been completed before it jumps to "finally"
I'm not storing the data in any database, just in public static string arrays in another class.
You have my code below:
if(networkAvailable()){
Thread splashTread = new Thread() {
#Override
public void run() {
try {
getData.execute(description_Hyperlinks);
getNews.execute(new String[]{newsJSON_Hyperlink});
getOffers.execute(new String[]{offersJSON_Hyperlink});
for(int i = 0; i<3; i++)
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
finish();
startActivity(new Intent(FlexFormActivity.this, MainMenu.class));
stop();
}
}
};
splashTread.start();
For the purpose of making the discussion in the comments on the initial question more readable and physically visible
It would be a better idea to use the Android build-in support for asynchronous task-handling in form of the AsyncTask-class. This allows you to "hook in" the task, giving you the opportunity to react on the different stages of the progress.
The idea would be to not make getData, getNews and getOffers each extend AsyncTask, but to rather have a single task (called e.g. "LoadContents"), which loads the data, the news and the offers one after another.
It would then be possible to determine, when the whole initial work has been done, which makes it easy to react on this "completion of task", in whatever form you can imagine.
As a little code-review, It should normally never be necessary to use the Thread-class itself, as Java and Android provide many wrappers around it (in particular the Java Executor Framework), which should be favored in order to produce more clean and reliable code.
Also, as a general advice on "disabling the back-button" (which is used by #Eugen to ensure that the splash-screen stays present): Don't do it. It's not the kind of behavior a user expects when he uses an application.
Imagine someone has accedently opened an app, which takes ~10 seconds for the initial loading of contents, and this process can't be canceled. The user will have to wait the entire time, only to then leave the app without using it.
Therefore, you should not "deactivate" the back-button, but rather make your task (and therefore the initial loading of your application) "cancel-able". When using an AsyncTask, this is already implemented for you.
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.