I'm fairly new to Android development and am currently working on an app that allows people to type text into a box and the text is displayed on a Bitmap on screen.
I have a text box in the activity that listens for changes. Each time you type text it calls functions to figure out how to best format the text on the image, then updates the image with the new text. It works fine for just a little bit of text, but when there's a lot, the calculations become slower and the device begins to freeze up, making typing nearly impossible.
Is there a way I can run the calculations in the background so that typing in the box is unaffected by the image updating? I'm thinking that using multiple threads would be useful, but don't know enough about threading to get it functioning.
Here's my code:
public class PicTextWatcher implements TextWatcher {
...
public void afterTextChanged(Editable editable) {
pic.setText(editable.toString()); //This function is relatively slow
pic.writeText(); //This function is very slow
imageView.setImageBitmap(pic.getImage()); //This doesn't need to happen every keystroke, only when the other functions have completely finished
}
}
Thanks in advance,
MrGrinst
You can use AsyncTask to do things in the background
public void afterTextChanged(final Editable editable) {
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
pic.setText(editable.toString());
pic.writeText();
return null;
}
protected void onPostExecute(Void result) {
imageView.setImageBitmap(pic.getImage());
}
}.execute();
}
You have to remember that now pic.setText(editable.toString());pic.writeText(); may be called simultaneously multiple times if the user typing fast and writetext is slow.
Related
I have created a splash screen for my app to hide the periodic insertion (after publishing updates) of a large number of records into the different tables of my app's SQLite database. I have been implementing an AsyncTask to handle the insertion off of the UI thread.
I need to create a ProgressDialog (with progress bar, not the simple spinning wheel) to inform the user of the current progress percentage for the insertion operations.
In most examples for setting the dialog's progress bar, the counter variable for the for loop representing the lengthy operation, or the percentage of file download is used to set this progress for the dialog. However, since insertions into different tables may take different amounts of time (depending on number of columns, etc), this approach appears to fail. The closest solution I could see would be to write a publishProgress(some_percentage) line after every record insertion in my doInBackground() method, using the % of records inserted as the parameter for publishProgress(), but this seems like a terribly inelegant and inefficient practice.
The current code for my AsyncTask implementation is below. Any suggestions for the best practice of determining the current progress percentage would be greatly appreciated. Thanks!
private class InsertionAction extends AsyncTask<Void,Integer,Void> {
Context context;
private ProgressDialog dialog;
private ForwardAction(Context context) {
this.context = context;
dialog = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.dialog.setMessage("Initializing Database. Please Wait...");
this.dialog.show();
this.dialog.getWindow().setGravity(Gravity.BOTTOM);
this.dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.dialog.setCancelable(false);
}
#Override
protected Void doInBackground(Void... params) {
// Large block of record insertions
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// Forward to the main activity
if (dialog.isShowing()) {
dialog.dismiss();
}
animatedTransition(SPLASH_DISPLAY_TIME/2);
}
#Override
protected void onProgressUpdate(Integer... values) {
}
}
Unfortunately there is no way to programmatically count your lines of code, calculate how much time they need to execute and generate an accurate time-proportionate progress.
I suggest updating the progress bar after a certain interval of lines, e.g. every 90 inserts (10%).
Or update according to what you are doing and modify the progress message (try to be creative), e.g. "Adding users", "Generating death rays", "Creating the universe", "Just a little longer", etc.
I have a problem that I want to change values on a screen after swiping views. I mean that when user flips their fingers on screen then a progress bar starts getting values from the server and set values after dismissal on the same screen.
I read many functionalities about ViewFlipper, ViewPager and Horizaontal Pager and many more but nothing finds like I want. Every Options needs all screen data at a time and then the same is responsible for showing it on every page in ViewFlipper.
Please suggest any solutions.
Would it work for you to launch an AsyncTask that will start the progress bar and then update the view when the new data from the server is available. This is slightly modified from the example in the class documentation at http://developer.android.com/reference/android/os/AsyncTask.html:
new GetServerValuesTask().execute(url1, url2, url3);
private class GetServerValuesTask extends AsyncTask<URL, Integer, String[]> {
protected String[] doInBackground(URL... urls) {
return getValuesFromServer(urls);
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(String[] values) {
updateViewWithNewValues(values);
}
}
I have four Tab at the top of my apps
The content of the fourth tab is that it will get data from sql server and then display in listview
since the amount of data retrieved is quite big, it takes 2-3 sec
The problem is that:
After I click the fourth tab, it has no response, then after 2-3sec, it displays the content
As I know it is loading the data from database, I will not continue to click
However, when users click it and no response, he may click and click and click
How to show something to user so that they know it is loading data??
You should use a CrusorLoader. This will display a loading circle while still making the UI active. Note that even if you're using lower versions of the android API, you can still access the CursorLoader class via the Android Support Package. For more information on loaders, checkout
new SomeTask(0).execute(); // write this line in your 4th tab onCreate()
/** Inner class for implementing progress bar before fetching data **/
private class SomeTask extends AsyncTask<Void, Void, Integer>
{
private ProgressDialog Dialog = new ProgressDialog(yourActivityClass.this);
#Override
protected void onPreExecute()
{
Dialog.setMessage("loading...");
Dialog.show();
}
#Override
protected Integer doInBackground(Void... params)
{
//Task for doing something
// get data from sql server and then display in listview
return 0;
}
#Override
protected void onPostExecute(Integer result)
{
if(result==0)
{
//do some thing if your list completed
}
// after completed finished the progressbar
Dialog.dismiss();
}
}
When a long-running process is started, you'll want to indicate that something is happening so the user knows to wait. You want a progress dialog.
Here is an example:
http://www.androidpeople.com/android-progress-dialog-example
I am learning Android via a book and would just like to confirm something.
When using AsyncTask according to the book it goes something like this:
main class
{
new AddStringTask().execute();
}
class AddStringTask extends AsyncTask<Void, String, Void> {
#Override
protected Void doInBackground(Void... unused) {
// Do something
SystemClock.sleep(333);
return(something);
}
#Override
protected void onProgressUpdate(String... item) {
// update something
}
}
which creates one background thread to do some stuff.
So if I want more threads, for example firing at different times (300, 500, 1000 milliseconds) then I need
to make even more sub classes... true?
Or is there some way to do multiple threads firing at different times using just this one subclass?
Thanks!
then I need to make even more sub classes... true?
Not true.
You can just execute the same AsyncTask again by creating a new AddStringTask() instance. This works since it'll be a new instance which differs from the other ones and each instance has its own thread. They are not interdependent.
However, the timer mechanism is something you have to implement yourself.
You could also use the same AsyncTask and publish diffrent progresses from the same thread. Let say :
protected Void doInBackground(Void... unused) {
...
System.sleep(500);
publishProgress(x);
System.sleep(500);
pulbishProgress(y);
}
and
protected void onProgressUpdate(String... progress) {
myLabel.setText(progress[0]);
}
I'm displaying some data by using SQLite. When I click on one button data come from database. It takes some time. At that time the screen is black. At that time I want to display the rotating spinner before the data dispay. Any ideas?
Android provides a ProgressDialog for accomplishing what you want.
First i would like to suggest to have a look at AsyncTask page, so that you will come to know about the AsyncTask exactly.
Now, Implement AsyncTask as given below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new performBackgroundTask().execute();
}
private class performBackgroundTask extends AsyncTask <Void, Void, Void>
{
private ProgressDialog Dialog = new ProgressDialog(main.this);
protected void onPreExecute()
{
Dialog.setMessage(getString("Please wait..."));
Dialog.show();
}
protected void onPostExecute(Void unused)
{
Dialog.dismiss();
// displaying all the fetched data
}
#Override
protected Void doInBackground(Void... params)
{
// implement long-running task here i.e. select query/fetch data from table
// fetch data from SQLite table/database
return null;
}
}
Enjoy !!!
You should not execute long running tasks in UI thread as this blocks the UI redraw and makes app look unresponsive.
Use AsyncTask to execute long running tasks in background, while still updating the screen.
You can look at the standard music picker as one example of how to do this:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java
In addition to the whole "queries must be done off the main UI thread," this shows an indeterminant progress while first loading its data, fading to the list once the data is available. The function to start the query is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#581
And to do the switch is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#569
The layout has the list view put in a frame layout with another container holding the progress indicator and label. The visibility of these is changed to control whether the list or progress indicator are shown:
https://android.googlesource.com/platform/packages/apps/Music/+/master/res/layout/music_picker.xml