I had a NullPointerException when I try to set ProgessBar to visible in onPreExecute AsyncTask (mProgressBar.setVisibility(View.VISIBLE);). I don't know what went wrong! Thanks you all!
<ProgressBar
android:id="#+id/pb_featured_game_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
/>
public class MainActivity extends Activity {
...
private ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
new FetchGamesTask().execute();
private class FetchGamesTask extends
AsyncTask<Integer, Integer, List<GameInfo>> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
mProgressBar = (ProgressBar)findViewById(R.id.pb_featured_game_progress);
mProgressBar.setVisibility(View.VISIBLE);
}
Before you call the execute on your FetchGamesTask, you should associate the main view with the xml file.
Like this
protected void onCreate(Bundle savedInstanceState) {
// the OS will inflate the main_activity.xml
// file and use it for this activity
setContentView(R.layout.main_activity);
new FetchGamesTask().execute();
Related
I'm trying to change the layout of my Activity through AsyncTask.
In onPostExecute() I'm calling:
MyActivity.this.setContentView(R.layout.activity_sub);
but it wont let me, saying "MyActivity is not an enclosing class".
Can anyone please help?
Shouldn't need the 'MyActivity.this.'; the below works for me:
public class MyAsyncTask extends AsyncTask<Void, Void, Integer> {
#Override
protected Integer doInBackground(Void... params) {
return R.layout.activity_home;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
setContentView(result);
}
}
I think this is a wrong way to change layout in activity in rutime. If you want to show a screen with another layout you should use fragments or create another one activity and set there up your layout.
It should work if you embed the AsyncTask class as an inner class of the activity.
public class MyActivity extends Activity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
...
public class MyAsyncTask extends AsyncTask<Void, Void, ...> {
#Override
protected ... doInBackground(Void... params) {
...
}
#Override
protected void onPostExecute(... result) {
super.onPostExecute(result);
setContentView(R.layout.activity_sub);
}
}
}
I have trouble displaying the layout of my main activity :
I create an ActivityA with an ImageView.
In onCreate(), I launch an AsyncTask, which retrieves content from Internet, and opens an ActivityB.
When I launch my application, it displays ActivityB right away.
public class ActivityA extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTask mytask = new MyTask();
mytask.execute();
}
}
My MainActivity xml file is the following :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/loadingPanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/home_page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_home_page" />
<ProgressBar
android:id="#+id/marker_progress"
style="?android:attr/progressBarStyle"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical|center_horizontal"
android:indeterminate="true" />
</RelativeLayout>
The ProgressBar is used to show the loading process of the AsyncTask.
thanks for helping
public class ActivityA extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTask mytask = new MyTask();
mytask.execute();
}
}
private class MyTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
// code for retrieve contents from Internet
}
#Override
protected void onPostExecute(String result) {
// cancel ProgressBar and start activity B here like
Intent i = new Intent(A.this, B.class);
startActivity(i);
}
#Override
protected void onPreExecute() {
// showing ProgressBar
}
}
don't forgot to mention A activity as a launcher.
I hope it will help you to solve this problem.
When I start activity with ListView it start to load some information from the Internet and after apply adapter, but during loading ListVIew doesn't show me a ProgressBar ring. When I trying to use SherlockListActivity instead ListView I have same problem.
<?xml version="1.0" encoding="utf-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/comments"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
public class CommentsActivity extends SherlockActivity{
#InjectView(R.id.comments) ListView mCommentsListView;
private String mPostId;
private CommentsAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.comment_activivty);
ButterKnife.inject(this);
Intent intent = getIntent();
mPostId = intent.getStringExtra("POST_ID");
LC lc = new LC();
lc.execute(mPostId);
}
public void setupAdapter(){
mAdapter = new CommentsAdapter(this);
mCommentsListView.setAdapter(mAdapter);
}
private class LC extends LoadComments{
#Override
protected void onPostExecute(Void result) {
//setup adapter after loading comments
setupAdapter();
}
}
}
Add ProgressBar to your layout file:
<ProgressBar
android:id="#+id/progress_bar"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Inject the ProgressBar in your activity:
#InjectView(R.id.progress_bar) ProgressBar mProgressBar;
Now you have to hide it when the adapter is set:
public void setupAdapter(){
mAdapter = new CommentsAdapter(this);
mCommentsListView.setAdapter(mAdapter);
mProgressBar.setVisibility(View.GONE);
}
Do it like this,
#Override
protected Void OnPreExecute(){
ProgressDialog prgDialog = new ProgressDialog(getContext());
prgDialog.setTitle("Loading");
prgDialog.setMessage("please wait")
prgDialog.setCancelable(false);
prgDialog.show();
}
on post Execute
private class LC extends LoadComments{
#Override
protected void onPostExecute(Void result) {
//setup adapter after loading comments
prgDialog.dismiss();
setupAdapter();
}
}
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
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.