start new Android Activity is so slow - android

I want to open a new Activity:
Intent intent = new Intent(homeScreen.this, EmployeeService.class);
Bundle b = new Bundle();
b.putInt(Constants.SERVICE_DETAIL_L1_ID_MSG, ServiceIndex.SRV_L1_EMPLOYMENT);
b.putInt(Constants.SERVICE_DETAIL_FOCUS_POS_MSG, 2);
intent.putExtras(b);
startActivity(intent);
But it takes so long to make destination Activity (EmployeeService) become visible. From Logcat, I see:
05-14 23:43:31.727: INFO/ActivityManager(59): Displayed activity fr.playsoft.happylille/.employee.EmployeeService: 7050 ms (total 7050 ms)
I cannot believe it take more than 7 seconds just to open a new Activity. I add a log in onCreate() but see it only take 5ms to finish onCreate.
Can anyone tell me how to find the root of this problem?

You should move the code Html.fromHtml(desc); to a thread to have it asynchronous. This thread can safely be started during the onCreate() of the newly opened Activity.
At the end of that thread, you can run tvDesc.setText() from the UI thread:
class ExampleThread extends Thread {
#Override
public void run() {
final Spanned spannedText = Html.fromHtml(desc);
yourNewlyOpenedActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
tvDesc.setText(spannedText);
}
});
}
}
More generally, 7 seconds on a device maybe means 20 on another, so beware the ANR!
(Edited further to Boy's comment below, the former version of this answer was no longer accurate/valid)

Shlublu's answer is incorrect, you are not allowed to do UI updates from non-UI threads!
It seems to work at first, but that is just luck, timing.
just a quick ugly test proves that it will go wrong at the 'right' timing. Here I set a text every 100 ms. Will crash in about 1 second:
new Thread() {
#Override
public void run() {
while (true) {
someTextView.setText("bla");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
It will throw this error: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
I think you should execute the Html.fromHtml(desc) via an AsyncTask or RxJava

your open new activity code put in Thread . and run code may be less time to required open another activity..may be helpfully.

Related

How do i add a delay to program before running selection query to avoid bind value being null?

I keep getting an illegal argument exception when running my app. However, this happens prior to the Toast messages coming up and that's why I think I need a delay.
Prior to adding on the DatabaseHelper class, my app was running and the proper value was coming up on both Toast messages, the one in the MainActivity and the one showing the intent value passed in the DisplayResult activity.
I'm not sure what to do at this point.
Just do a thread sleep in a runnable.
int timeYouWantToSleep = 60000;
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(timeYouWantToSleep);
//do your work here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
If this doesn't work, you know it's not a delay that you need.

Thread is not actually working

I'm a noobie in Java and Android I have a Thread question:
I have the following code that is triggered from android:onClick on the xml layout
The resulting behavior is that the UI waits 5 seconds and only after those 5 seconds, the ProgressDialog starts.
Shouldn't the Thread start independently and the dialog pop immediately?
Why is the Thread stopping the course of the procedure?
Thanks!
// (Button)
public void buttonReadGps(View v){
Thread readingGps = new Thread(){
public void run() {
// Read GPS code will go here
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
readingGps.run();
// Create a wait dialog
prgDialg = new ProgressDialog(context);
prgDialg.setTitle("Reading GPS...");
prgDialg.setMessage("Please wait.");
prgDialg.setCancelable(true);
prgDialg.setIndeterminate(true);
prgDialg.show();
}
Replace
readingGps.run();
with
readingGps.start();
The problem is the first version will just run your method synchronously and block the main thread. The second version actually starts a thread and continues, so the method will run asynchronously on a new thread.
This is such a common pattern in Android that the SDK gives a few classes to help: be sure to check out AsyncTask and possibly AsyncTaskLoader.

Implementing a while loop in android

I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();

Task not finishing and forbidding TextView to be updated

I am now working on an android app in which I need to display a text after some processing is done.
I'm using a Thread to run a process in the back while my progress dialog is being displayed to the user. The Thread works properly and I've followed it step by step and, apparently, it also ends fine; however, the method in which I call it does not seem to come to an end (at least, during a normal cycle) because the text I am setting afterward does display immediately, I have to wait and do some other action (like in order for it to display
Below is the piece of code I'm having trouble with:
private OnClickListener saldoDisp = new OnClickListener(){
public void onClick(View v){
int x = s2.getSelectedItemPosition();
branchSel = arrSucsId[x];
mainProc();
saldoAdminTex.setText(strSaldo); //The late one
}
};
public void mainProc(){
chekP = new Thread (null,doProc,"Background");
chekP.start();
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true, false);
}
private Runnable doProc = new Runnable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
};
So I do get the "Task completed properly" but seems like it still waits for something else, any clues guys?
Thanks for taking a bit of your time to check it out =).
saldoAdminTex.setText(strSaldo); //The late one
is going to get called immediately. It doesn't wait until after the Thread started in mainProc ends. You also cannot dismiss the Progress Dialog in your runnable. You can only do UI related things on the main UI thread.
It would help you to read the article on Painless Threading on the Android Dev site.
About your ProgressDialog, please see this answer about how to use a AsyncTask with a ProgressDialog.
Looking at your code, this:
saldoAdminTex.setText(strSaldo);
would potentially be executed before your thread finishes as the thread will be running in parallel to that line.
An alternative way would be to do this:
public void mainProc(){
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true,false);
handler.post(new Runable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
saldoAdminTex.setText(strSaldo);
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
});
}

Android: Stopping method to be called twice if already running

I am trying to prevent my application calling the same method twice in the event of a double-click, or if the user presses different buttons quickly, almost at the same time.
I have clickable Views, acting as buttons, that call the same method but passing different parameters. This is the call:
startTheSearch(context, getState(), what, where);
Inside this method I'm creating a new Thread, because it queries a web server for the result:
new Thread(new Runnable() {
public void run() {
progDiag = ProgressDialog.show(ctx, null, "Searching", true);
getServerXML(context, what, where, searchIsCustom, mOffset);
handler.sendEmptyMessage(0);
}
}).start();
The problem is that upon two quick clicks, the method is fired twice, two threads are created, and consequently two new activities are created. That makes my app crash.
When the methods are done, and we have the result from the server, we call the handler:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
Intent i = new Intent(Golf.this, Result.class);
Bundle b = new Bundle();
b.putString("what", mWhat);
b.putString("where", mWhere);
b.putInt("offset", mOffset);
b.putBoolean("searchIsCustom", searchIsCustom);
i.putExtras(b);
startActivityForResult(i, Activity.RESULT_OK);
progDiag.dismiss();
} catch (Exception e) {
Alerts.generalDialogAlert("Error", "settings", ctx);
}
}
};
I tried to have a global boolean variable called "blocked" initially set to false, creating a condition like:
if(!blocked){
blocked = true;
new Thread(new Runnable() {
public void run() {
But this only seems to work on slower phones like the G1, I tried on Nexus and before it set blocked = true, the second request has was granted. So is there any way I can block the method being called if it's already running, or if the thread has started so it wont create a new one?
In the book Hello Android the author Ed Burnette gives a very nice solution for this problem.
To leave your app snappy and responsive you should create a second thread to do the web request.
Instead of creating a new thread for every request you can use a SingleThreadExecutor. If you start a second thread you can check if you are waiting for the result of another thread and block until this thread is ready, or cancel the old thread and start a new one if you think that the user now wants to do some other thing.
You can find the source code from the book on this page. Look for the Translate folder inside the source. It is a nice example on how to react to user commands and how to prevent too many web requests because of a user touching a lot on the gui.
Instead of using the "blocked" Boolean, you might investigate using a mutex. They're designed for this kind of problem.
I tried on Nexus and before it set
blocked = true, the second request has
was granted
That is impossible. Android UIs are single-threaded. There is no way that two onClick() methods of OnClickListeners will be called at the same time.

Categories

Resources