Error in simple AsyncTask - android

In my android app, I am trying to make use of ASYNC Task ... whenever I set text of any TextView of EditText in doInBackground(...) .... I get an error , but when I set the same in onCreate , it works .. :(
here is the code :
public class RemoteFiles extends Activity {
EditText etrmm ;
TextView t;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remote_files);
initVars();
new ConnectToServer().execute(null);
}
protected void initVars(){
etrmm =(EditText)findViewById(R.id.etRM);
etrmm.setText("UnSET");
t=(TextView)findViewById(R.id.RM);
t.setText("UnsET");
}
public class ConnectToServer extends AsyncTask<String, Integer, Void> {
//private ProgressDialog pd = new ProgressDialog(RemoteFiles.this);
private ProgressDialog pdd ;
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
publishProgress(5);
try {
Thread.sleep(88);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
etrmm.setText("Edittext SET");
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pdd.dismiss();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
// pd.setMessage("Connecting to server... ");
// pd.show();
pdd = new ProgressDialog(RemoteFiles.this);
pdd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pdd.setMax(100);
pdd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
pdd.incrementProgressBy(values[0]);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_remote_files, menu);
return true;
}}
here is the layout :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/RM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/padding_medium"
android:text="#string/hello_world"
tools:context=".RemoteFiles" />
<EditText
android:id="#+id/etRM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10" >
<requestFocus />
</EditText>
logcat says android.view.ViewRoot$CalledFromWrongThreadException

doInBackground(String... params) not run on UI Thread, so you can't set text for edittext there
if you want to set edittext value, return the value in doInBackGround and use the parameter value in onPostExecute and set it in onPostExecute()

You can't do UI stuff in doInBackground(). This should be done in any of the other methods. For your purposes, probably onPostExecture()
Take a look at the AsyncDocs, doInBackground() doesn't run on the main (UI) thread

AsyncTask's onpreExecute and onPostExecute methods run o UI Thread. You can make changes to the UI here. doInBackground does not run on UI thread. It is used to do long Running operations. Runs in the background thread. You cannot update ui from the background thread in doinBackground.
Set text in textview in onPostExecute method of asynctask.
The document in the developer site has detailed information regarding the topic under the heading THE 4 STEPS. http://developer.android.com/reference/android/os/AsyncTask.html

Related

AsyncTask concurrency issue

i am using Asynctask to do network operation .i am using third party library to fetch data from my database.
Problem
i am hitting query in doInBackgroun method of my asynctask that eventually call a callback method which has result to display.But onPostExecute method get called before the callback method call itslef .Hence data is never attached to adapter which i set in onPostExecute.
Issue:how to wait doInbackground method to return until the callbackmethod get called.So that i can call onPostExecute method after data get available.
below is my asyntTask and call back method is onCompleted.
in my onPostExecute i am using data to display it in adapter.so i havent fully posted it because it is bunch of code.
public class MyReviewLoadingTask extends AsyncTask<Void, Void, List<WYF_User_Items>>
{
ProgressDialog pdilog;
List<WYF_User_Items> result_to_send_to_adapter;
#Override
protected void onPreExecute()
{
// TODO Auto-generated method stub
super.onPreExecute();
pdilog=new ProgressDialog(SingleReviewActivity.this);
pdilog.setIndeterminate(true);
pdilog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pdilog.setMessage("please wait");
pdilog.setTitle("Review Details");
pdilog.show();
}
#Override
protected List<WYF_User_Items> doInBackground(Void... params)
{
// TODO Auto-generated method stub
getDatabaseTable();
MobileServiceQuery<WYF_User_Items> query=new MobileServiceQuery<WYF_User_Items>();
query.select("review_rating","review_body","unique_user_id","userName");
wyf_user_item_table.where().field("brand_name").eq(review_name).execute(new TableQueryCallback<WYF_User_Items>() {
#Override
public void onCompleted(List<WYF_User_Items> result, int arg1,
Exception arg2, ServiceFilterResponse arg3) {
// TODO Auto-generated method stub
Log.i(TAG, "size is "+result.size());
result_to_send_to_adapter=result;
for(int i=0;i<result.size();i++)
{
Log.i(TAG, "unique user id of all user who has entered review is "+result.get(i).getUnique_user_id()+" and their names are "+result.get(i).getUserName());
}
}
});
wyf_user_item_table.select("review_rating").add(new MobileServiceQuery<WYF_User_Items>());
return result_to_send_to_adapter;
}
#Override
protected void onPostExecute(List<WYF_User_Items> result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.i(TAG, "onPostExecute called");
pdilog.dismiss();
You do need an AsyncTask for this usecase imo. If the MobileQueryService runs on a different Thread already, just implement your logic on the callback onCompleted provided.

Executing two asynctask in in two different classes

I have 2 AsyncTasks in two different classes but the problem is when the first is do in backgroung state the second is not executed. The first asyncTask if preformed in loop because it needs to update every 5 seconds the new data. If i stop the task (condition = flase) the second one works perfectly.
First class:
public class MapScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_screen);
UpdateUserCords updateUC = new UpdateUserCords();
updateUC.execute();
}
class UpdateUserCords extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params) {
while(condition)
{
//some code in loop...
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}
Second class:
public class Groups extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_groups);
getGroups getGr = new getGroups();
getGr.execute(); //not executing, no error or crash
}
class getGroups extends AsyncTask<String, Void, String>
{
ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
#Override
protected String doInBackground(String... params) {
//some code...
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}
After Android API 11, AsyncTasks started to run on serial executor by default, that means that only one task is running at a time. To get the behavior of prior to API 11, which is running on ThreadPoolExecutor, you'll need to specify it in the code like this:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
myTask.execute();
}
Please take a look here for more information:
http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html
Good luck!
P.S. It's not recommended to use AsyncTask for an infinite thread, AsyncTask purpose is to do a Task on the background, not to run forever, so if you want an infinite thread, I think you should create it as a Thread and not as an AsyncTask.
You asynctasks are in two different activities.
Only one activity is active at any time.
Both classes extend Activity and only one of them is running at the same time.
If you want a task to be execute longer than the lifetime of an activity, you have to wrap it into an Service

How to create a custom Progress Dialog(spinner)?

I have googled a lot and even gone through many of this website questions but I just can't find the solution to my problem.
I want to create a spinner like the one below. This is just a normal spinner I have done till now. I tried a variety of spinner examples but they don't give me my desired result.
Here is my code:
public class nextclass extends Activity {
Thread t;
ProgressBar dia;
private ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
MainActivity.progressDialog.dismiss();
setContentView(R.layout.nextclassview);
// requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
((Button) findViewById(R.id.button1))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// progressDialog = findViewById(R.id.progressBar1);
new AuthenticateUserTask().execute();
}
});
}
private class AuthenticateUserTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progressDialog = ProgressDialog.show(
nextclass.this, "","Sucessful", true);
/* progressDialog.setIndeterminate(true);
progressDialog.setIndeterminateDrawable(getResources()
.getDrawable(R.layout.customspinner));
*/
progressDialog = ProgressDialog.show(nextclass.this, "",
"Processing....", true);
progressDialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
protected void onPostExecute(String s) {
if (progressDialog.isShowing())
progressDialog.dismiss();
Intent my = new Intent(getApplicationContext(), CountTime.class);
startActivity(my);
}
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);![custom spinner][2]
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
}
I Don't have Seen any Spinner in your Code. but Anyway you can use below code for making Custom Spinner.
Inside your Layout File:
<Spinnerandroid:id="#+id/spinnerview"
android:layout_width="180dp"
android:layout_height="42dp"
android:layout_marginLeft="105dp"
android:layout_marginTop="45dp"
android:background="#drawable/spinner_back"
android:paddingLeft="5dp"
android:spinnerMode="dropdown"android:visibility="visible" />
inside your String.xml :
<string-array name="spinner_array_environtment">
<item>Test</item>
<item>Production</item>
</string-array>
inside you Java File in OnCreate Method:
spinner_environment = (Spinner) findViewById(R.id.spinnerview);
adapter = ArrayAdapter.createFromResource(this,
R.array.spinner_array_environtment, R.layout.spinner);
adapter.setDropDownViewResource(R.layout.spinner);
spinner_environment.setAdapter(adapter);
Make new spinner.xml file to your layout folder :
inside spinner.xml file :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/spinnerTarget"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:textColor="#4C4646" />
Thats it!!!

Show ProgressBar in another thread

For a few days a have some problem.
I need to show simple ProgressBar (not dialog) while doing some stuff in main thread...
I thought its a very simple question, but i cant do this, help me please.
First i tried simple setVisibility(View.VISIBLE) before and setVisibility(View.GONE) after.
But this is doing in the same thread, and ProgressBar freezed while my function working.
Now i have this code, but i have some error, and i dont know whats wrong..
my simple layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
i have a base activity :
public class BaseActivity extends Activity {
public ProgressBar loading;
public class ProgressBarShow extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... unused) {
return(null);
}
protected void onProgressUpdate() {
}
protected void onPreExecute() {
loading.setVisibility(View.VISIBLE);
}
protected void onPostExecute() {
}
}
}
and finally my working activity , which extends BaseActivity
public class SearchActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loading = (ProgressBar) findViewById(R.id.loading);
new ProgressBarShow().execute();
//doing long stuff
//new ProgressBarHide().execute(); there isnt, but sense the same
}
}
I have many activities, which need progress bar, thats why i have created BaseActivity,
to not to dublicate code.
I need to do long work (stuff function) in main thread, because i want to freeze main window and not to allow user do anything (click button etc..), just show working ProgressBar.
Whats wrong in my example? Or give me some advice how can i do this better
class ProgressTask extends AsyncTask<Integer, Integer, Void>{
ProgressBar progress;
Context context;
public ProgressTask(ProgressBar progress, Context context) {
this.progress = progress;
this.context = context;
}
#Override
protected void onPreExecute() {
// initialize the progress bar
// set maximum progress to 100.
progress.setMax(100);
}
#Override
protected Void doInBackground(Integer... params) {
// get the initial starting value
int start=params[0];
// increment the progress
for(int i=start;i<=100;i+=5){
try {
boolean cancelled=isCancelled();
//if async task is not cancelled, update the progress
if(!cancelled){
publishProgress(i);
SystemClock.sleep(1000);
}
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
return null;
}
//Has direct connection to UI Main thread
//Called everytime publishProgress(int) is called in doInBackground
#Override
protected void onProgressUpdate(Integer... values) {
progress.setProgress(values[0]);
Toast.makeText(context, "test"+values[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(Void result) {
// async task finished
Log.v("Progress", "Finished");
}
#Override
protected void onCancelled() {
progress.setMax(0);
}
}
Use AsyncTask http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html Put your ProgressBar in it, while all work is doing in main thread

Updating TextView from Async Task which use custom program dialog

In one of my app, I have a scenario where I need to do some background task. For doing that I am using Async Task. Also I am using custom progress dialog. Below is the layout of the custom progress dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="vertical" >
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateDrawable="#drawable/progressloader"
android:layout_gravity="center"/>
<TextView
android:id="#+id/progressMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textSize="18sp"
android:text="Please wait...." />
</LinearLayout>
Everything works fine but when I try to set text to TextView then I am getting java NullPointerException.
AsyncTask code
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
}
#Override
protected Long doInBackground(String... urls) {
// txtView.setText("Testing"); here I am getting the error
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
MainActivity
public class SummaryActivity extends Activity {
final TextView txtView = (TextView)findbyid(R.id.progressMessage);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
new InitialSetup().execute("");
}
}
If I understand correctly, your TextView of which you want to set the text can be found in the xml file progressbar.xml (i.e. R.layout.progressbar). This TextView can be obtained once the content view has been set (using setContentView()). In your code you set it before this call is been and the code of mussharapp, he is calling it to early. Namely, he calls it after the setContentView(R.layout.accountsummary) call which does not contain the TextView. Consequently, the variable txtView will be NULL and you will get a NullPointerException.
What you should do is the following:
Set the variable txtView in onPreExecute, after setContentView is called.
Based on Paresh Mayani's explanation: Use the runOnUiThread method.
For the code look down below:
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
// Already suggested by Paresh Mayani:
// Use the runOnUiThread method.
// See his explanation.
runOnUiThread(new Runnable() {
#Override
public void run() {
txtView.setText("Testing");
}
});
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed,
Why not allowed? Because There is a only one Thread running which is UI Main Thread, and it doesn't allowed to update UI from thread process. read more info here: Painless Threading
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
(TextView)findViewByid(R.id.progressMessage);
should only be executed after the command setContentView().
TextView txtView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
**txtView = (TextView)findbyid(R.id.progressMessage);**
new InitialSetup().execute("");
}
Also you can only change UI elements in the main UI thread. doInBackground() is not in the main UI thread. Make UI changes in onPostExecute
public class InitialSetup extends AsyncTask<String, Integer, Long> {
private Activity activity;
ProgressDialog progressDialog;
public InitialSetup(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Starting task....");
progressDialog.show();
}
#Override
protected Long doInBackground(String... urls) {
// do something
//
return 0;
}
#Override
protected void onPostExecute(Long result) {
progressDialog.dismiss();
//Perform all UI changes here
**textView.setText("Text#2");**
}
}
The explanations are correct: You are not to make UI changes in any thread except the thread which create the UI. But AsyncTask has a method called
onProgressUpdate()
which always will run in the UI Thread. So based on the modifications by dennisg your code should look like this:
private class InitialSetup extends AsyncTask<String, String, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
publishProgress("Testing");
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
#Override
protected void onProgressUpdate(String... update) {
if (update.length > 0)
txtView.setText(update[0]);
}
}
Note that the type of the parameter of onProgressUpdate is the second type given in AsyncTask!
Extra: To make your code more robust you should check if the progress dialog still exists before setting the text.

Categories

Resources