Android: Arrayoutofindexbounds with Thread - android

I have a little problem with my code. I keep getting an arrayoutofindexbounds with the following code:
public boolean checksouth(int r,int c, int numofwords) {
if (south==false)
{return false;}
computer_find=0;
for (int x=0;x<=(numofwords-1);x++)
{
if (worduniverse[(r-x)][c]==computer_words[x]) **bold**<=Problem arises here>
{
computer_find++;
}
}
if ((computer_find==numofwords)&&(numofwords!=0))
{
r_computer=r;
c_computer=c;
direction_computer=2;
highlight_num=numofwords;
return true;
}
return false;
}
My objective is to create a Word search protocol that would not use the UI. When I put the code into the UI the system kept giving me an ANR.
However the code, while in UI, never gave me an Arrayoutofindex. The arrayoutofindex only occurs once the code is called from another thread. I cannot understand this. Any help would be appreciated.
I must point out that the code accurately worked outside the Thread. When it was put into another thread it gave me false results. I need the thread in order to reduce possibility of ANR in my app.
The Logcat output simply points to the location I have highlighted.

You can use AsyncTask insted :
http://developer.android.com/reference/android/os/AsyncTask.html

Wow, I like to thank all for the help. I achieved my objective by simply including all code into one method. Was a lot faster and did not give me an ANR.
I was always getting an ANR because I had multiple methods to help me do brute force word alogrithnm. Weedled the methods down to one and the search took less than 1.5 seconds on an Android phone.

Related

Device goes black and Launch timeout expires

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.

Unexpected behavior of same methods in different threads

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.

Running JUnit test multiple times gives different results

I have a test case for my app which fills in the TextViews in an Activity and then simulates clicking the Save button which commits the data to a database. I repeat this several times with different data, call Instrumentation.waitForIdleSync(), and then check that the data inserted is in fact in the database. I recently ran this test three times in a row without changing or recompiling my code. The result each time was different: one test run passed and the other two test runs reported different data items missing from the database. What could cause this kind of behavior? Is it possibly due to some race condition between competing threads? How do I debug this when the outcome differs each time I run it?
Looks like a race condition.
remember in the world of threading there is no way to ensure runtime order.
I'm not an android dev so I'm only speculating but UI is only on one event thread generally so when you call the method from another thread (your test) you're probably breaking that as you're outside of the event thread.
You could try using a semaphore or more likely a lock on the resource.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html
I (finally!) found a solution to this problem. I now call finish() on the tested Activity to make sure that all of its connections to the database are closed. This seems to ensure consistency in the data when I run the assertions.
I would suggest making a probe for the database data rather than a straight assert on it. By this I mean make a piece of code that will keep checking the database for up to a certain amount of time for a condition rather than waiting for x seconds (or idle time) then check, I am not on a proper computer so the following is only pseudo code
public static void assertDatabaseHasData(String message, String dataExpected, long maxTimeToWaitFor){
long timeToWaitUntil = System.getCurrentTimeMillis() + maxTimeToWaitFor;
boolean expectationMatched = false;
do {
if(databaseCheck() == dataExpected){
expecttionMatched == true;
}
}while(!expectationMatched && System.getCurrentTimeMillis() < timeToWaituntil);
assertTrue(message, expectationMatched);
}
When i get to a computer i will try to relook into the above and make it better (I would actually of used hamcrest rather than asserts but that is personal preference)

How to confirm if a task is completed before finalizing the thread?

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.

Android accessing UI from second thread

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
}

Categories

Resources