Progress Dialog in Twitter Async Task - Android - android

I want to bring up a progress dialog when the user loads up the twitter feed and when the twitter feed has loaded the progress dialog disappears.
This is the TwitterAsyncTask class:
public class TwitterAsyncTask extends AsyncTask<Object, Void, ArrayList<TwitterTweet>> {
ListActivity callerActivity;
private ProgressDialog pd;
final static String TWITTER_API_KEY = "ddd";
final static String TWITTER_API_SECRET ="fffff";
Context cnt;
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(cnt.getApplicationContext());
pd.setMessage("loading");
pd.show();
}
#Override
protected ArrayList<TwitterTweet> doInBackground(Object... params) {
ArrayList<TwitterTweet> twitterTweets = null;
callerActivity = (ListActivity) params[1];
if (params.length > 0) {
TwitterAPI twitterAPI = new TwitterAPI(TWITTER_API_KEY,TWITTER_API_SECRET);
twitterTweets = twitterAPI.getTwitterTweets(params[0].toString());
}
return twitterTweets;
}
#Override
protected void onPostExecute(ArrayList<TwitterTweet> twitterTweets) {
ArrayAdapter<TwitterTweet> adapter =
new ArrayAdapter<TwitterTweet>(callerActivity, R.layout.twitter_tweets_list,
R.id.listTextView, twitterTweets);
callerActivity.setListAdapter(adapter);
ListView lv = callerActivity.getListView();
lv.setDividerHeight(0);
lv.setBackgroundColor(callerActivity.getResources().getColor(R.color.white));
if (pd != null)
{
pd.dismiss();
}
}
}
And here is the class that calls the TwitterAsyncTask class:
public class MainActivity extends ListActivity {
final static String twitterScreenName = "CFABUK";
final static String TAG = "MainActivity";
private AsyncTask<Object, Void, ArrayList<TwitterTweet>> tat;
boolean done;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
done = false;
AndroidNetworkUtility androidNetworkUtility = new AndroidNetworkUtility();
if (androidNetworkUtility.isConnected(this)) {
new TwitterAsyncTask().execute(twitterScreenName, this);
} else {
Log.v(TAG, "Network not Available!");
}
}
public void timerDelayRemoveDialog(long time, final ProgressDialog d) {
new Handler().postDelayed(new Runnable() {
public void run() {
d.dismiss();
}
}, time);
}
}
the error seems to appear for the line pd = new ProgressDialog(cnt.getApplicationContext());...What should I put for this? thanks

Just add Constructor in your AsyncTask like
Context mContext;
public TwitterAsyncTask(Context mContext){
this.mContext=mContext;
}
And from your activity
Context mContext=this;
new TwitterAsyncTask(mContext).execute(twitterScreenName, this);

Instead of cnt.getApplicationContext() replace it with YourClassName.this

Embed your Async task in your activity, and replace your Context cnt by YourActivity.class... And please include some log.

Related

how to call an intent from a different class

I am trying to call an intent from a handler and I don't know how to do it. I have tried many different ways but it does't seem to be working. I want to start the PrimeNumbersActivity when the progress dialog reaches its max.
public class MyHandler extends Handler {
ProgressDialog progressDialog;
Context context;
public MyHandler(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
public MyHandler(Context context){
this.context = context;
}
#Override
public void handleMessage(Message msg) {
findPrimeNumber(Integer.parseInt(msg.obj.toString()));
}
public void findPrimeNumber(int number){
ArrayList<Integer> primeNumbers = new ArrayList<>();
boolean isPrimeNumber;
PrimeNumbers primeNumbers1 = new PrimeNumbers();
for(int i = 2; i <= number; i++){
isPrimeNumber = true;
for(int j = 1; j <= i; j++){
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(j != 1 && j != i){
if(i%j == 0){
isPrimeNumber = false;
break;
}
}
}
if(isPrimeNumber){
primeNumbers.add(i);
primeNumbers1.primeNumbers.add(i);
}
progressDialog.setProgress(i*100/number);
if(progressDialog.getProgress() == progressDialog.getMax()){
progressDialog.dismiss();
Intent intent = new Intent(context.getApplicationContext(),PrimeNumbersActivity.class);
context.startActivity(intent);
}
}
for (int i :
primeNumbers) {
Log.d(TAG, i + "");
}
}
}
the PrimeNumbersActivity
public class PrimeNumbersActivity extends AppCompatActivity {
private PrimeNumbers primeNumbers = new PrimeNumbers();
private ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prime_numbers);
listView = findViewById(R.id.listView);
if(primeNumbers.primeNumbers.isEmpty()){
Toast.makeText(getApplicationContext(),"Pas de nombres premiers",Toast.LENGTH_SHORT).show();
}else{
ArrayAdapter<Integer> arrayAdapter = new ArrayAdapter<Integer>(getApplicationContext(),android.R.layout.simple_list_item_1,primeNumbers.primeNumbers);
listView.setAdapter(arrayAdapter);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
public static final int number = 20;
public Button button;
public EditText editText;
public ProgressDialog progressDialog;
public AlertDialog.Builder alertDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMax(100);
progressDialog.setMessage("Please wait...");
progressDialog.setTitle("Finding prime numbers");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
final MyThread thread = new MyThread(progressDialog);
thread.setName("MyThread");
thread.start();
button = (Button) findViewById(R.id.afficherNombrePremier);
editText = (EditText) findViewById(R.id.editText);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(editText.getText().toString().isEmpty()){
alertDialog = new AlertDialog.Builder(MainActivity.this);
alertDialog.setTitle("Warning");
alertDialog.setMessage("Veuillez saisir un nombre entier dans la zone de texte");
alertDialog.show();
}
else{
progressDialog.show();
Message message = Message.obtain();
message.obj = editText.getText().toString();
thread.mHandler.sendMessage(message);
}
}
});
}
}
Error:
04-24 00:45:15.457 4625-4712/com.example.mohammed.tdservicesex1 E/AndroidRuntime: FATAL EXCEPTION: MyThread
Process: com.example.mohammed.tdservicesex1, PID: 4625
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at com.example.mohammed.tdservicesex1.MyHandler.findPrimeNumber(MyHandler.java:65)
at com.example.mohammed.tdservicesex1.MyHandler.handleMessage(MyHandler.java:31)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at com.example.mohammed.tdservicesex1.MyThread.run(MyThread.java:22)
Thread:
public class MyThread extends Thread {
private static final String TAG = MyThread.class.getSimpleName();
public MyHandler mHandler;
ProgressDialog progressDialog;
public MyThread(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
#Override
public void run() {
Looper.prepare();
mHandler = new MyHandler(progressDialog);
Looper.loop();
}
}
The error is happened because you haven't set any context with your constructor in your MyHandler class. Your constructors is like the following:
public class MyHandler extends Handler {
...
public MyHandler(ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
public MyHandler(Context context){
this.context = context;
}
...
}
you can see that you have 2 different constructors. In your code, you're only using the first constructor, you never assign the context with your second constructor. This is a common error when you're using multiple constructor for a class.
To solve the problem, you need to change your constructor so that it needs two parameters: ProgressDialog and Context. Change the constructor to something like this:
public class MyHandler extends Handler {
...
public MyHandler(ProgressDialog progressDialog, Context context) {
this.progressDialog = progressDialog;
this.context = context;
}
...
}
I believe you cannot start an activity using the application context (in a straightforward manner). You either have to
Use activity context
Use application context but add this flag FLAG_ACTIVITY_NEW_TASK
Be warned that FLAG_ACTIVITYNEW_TASK will start a new task in the history stack
Try something like this:
Intent intent = new Intent(context.getApplicationContext(),PrimeNumbersActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Make sure you declared PrimeNumbersActivity in Android Manifest
This should work:
Intent intent = new Intent(context,PrimeNumbersActivity.class);
context.startActivity(intent);
If #2 does not work. It means this condition is always false:
if(progressDialog.getProgress() == progressDialog.getMax())

doInBackground() method in an AsyncTask doesn't work when the activity is being re-opened

In my Android app, I have an activity which executes an AsyncTask<Void, Void, Void> named Scan using this code: new Scan().execute();.
In the onPreExecute() method, it starts a progress dialog, on the doInBackground(Void... voids) method it scans a table from DynamoDB, and on the onPostExecute(Void aVoid) method, it dismisses the progress dialog, and views the results of the DB scan in a ListView using a custom BaseAdapter class.
When I open the activity, everything runs great, but when I press the back button, and enter the activity again, then only the onPreExecute() and the onPostExecute(Void aVoid) methods are being executed, while doInBackground(Void... voids) isn't being executed, so it just shows and dismisses the progress dialog, and nothing else is being viewed on the screen.
How can I fix this?
Code:
MessagesListAdapter messages;
ListView messagesLv;
public static ArrayList<Message> arrayList;
public static ProgressDialog progressDialog;
public static DynamoDBScanExpression dbScanExpression;
public static List<Message> messageList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messages);
new Scan().execute();
}
private class Scan extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(TestActivity.this);
progressDialog.setTitle(name);
progressDialog.setMessage("Searching for messages...");
progressDialog.setIndeterminate(false);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
dbScanExpression = new DynamoDBScanExpression();
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(MainActivity.msgId));
dbScanExpression.addFilterCondition("msgId", condition);
messageList = MainActivity.mapper.scan(Message.class, dbScanExpression);
arrayList = new ArrayList<Message>();
for (Message msg : messageList) {
if (msg.getUserId() == null || msg.getUserId().equals(MainActivity.userId)) {
msg.setMsgId(msg.getMsgId());
msg.setDate(msg.getDate());
msg.setTime(msg.getTime());
msg.setMessage(msg.getMessage());
msg.setUserId(msg.getUserId());
arrayList.add(msg);
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (!messageList.isEmpty()) {
messagesLv = (ListView) findViewById(R.id.messagesListView);
messages = new MessagesListAdapter(MinaActivity.this, arrayList);
messagesLv.setAdapter(messages);
progressDialog.dismiss();
} else {
TextView tv = (TextView) findViewById(R.id.noMessages);
tv.setVisibility(View.VISIBLE);
progressDialog.dismiss();
}
}
}
The reason that it couldn't find any messages, was that I checked if the user ID of the message equals to the user ID of the registered user. The problem was that it was taken from MainActivity.java which got it from an Intent extra, therefore, when I have left the activity, the variable has been erased.
What I did is to refer to the user ID from the SharedPreferences and suddenly it worked.
try to add messages.notifyDataSetChanged(); in onPostExecute() method.
or use below code
MessagesListAdapter messages;
ListView messagesLv;
public static ArrayList<Message> arrayList;
public static ProgressDialog progressDialog;
public static DynamoDBScanExpression dbScanExpression;
public static List<Message> messageList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messages);
messagesLv = (ListView) findViewById(R.id.messagesListView);
messages = new MessagesListAdapter(MinaActivity.this, arrayList);
messagesLv.setAdapter(messages);
new Scan().execute();
}
private class Scan extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(TestActivity.this);
progressDialog.setTitle(name);
progressDialog.setMessage("Searching for messages...");
progressDialog.setIndeterminate(false);
progressDialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
dbScanExpression = new DynamoDBScanExpression();
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(MainActivity.msgId));
dbScanExpression.addFilterCondition("msgId", condition);
messageList = MainActivity.mapper.scan(Message.class, dbScanExpression);
arrayList = new ArrayList<Message>();
for (Message msg : messageList) {
if (msg.getUserId() == null || msg.getUserId().equals(MainActivity.userId)) {
msg.setMsgId(msg.getMsgId());
msg.setDate(msg.getDate());
msg.setTime(msg.getTime());
msg.setMessage(msg.getMessage());
msg.setUserId(msg.getUserId());
arrayList.add(msg);
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (!messageList.isEmpty()) {
messages.notifyDataSetChanged();
progressDialog.dismiss();
} else {
TextView tv = (TextView) findViewById(R.id.noMessages);
tv.setVisibility(View.VISIBLE);
progressDialog.dismiss();
}
}
}

Android display a ProgressDialog on a ListActivity when using multiple external AsynTasks

So I am completely new to Andorid programming and can't seem to get a ProgressDialog to show on a ListActivity (ScheduleActiviy in my example) when running an AsyncTask from a separate class (GetGames in my example). I am attempting to use separate class for code re-usability. When I previously had the AsyncTask as an embedded class it seemed to work. I have posted what I believe to be all the relevant code. Any help would be great. Thanks!
ScheduleActivity.java
public class ScheduleActivity extends ListActivity
{
private final String PDIALOG_MSG = "Loading schedule...";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.schedule);
ArrayList<HashMap<String, String>> gamesList = null;
try
{
// Loading information in Background Threads
gamesList = new GetGames(ScheduleActivity.this, PDIALOG_MSG).execute().get();
GetGames.java
public class GetGames extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>>
{
private Context context;
private ProgressDialog pDialog;
private String pDialogMsg;
public GetGames(Context ctx, String dialogMsg)
{
context = ctx;
pDialogMsg = dialogMsg;
}
#Override
public void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage(pDialogMsg);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
public void onPostExecute(ArrayList<HashMap<String, String>> rtnList)
{
pDialog.dismiss();
}
Your ProgressDialog should probably be controlled on the Activity level instead of the AsyncTask level. Theoretically I don't see why how you're doing it wouldn't work, but I can show you a method which definitely works (it's what I do) and it organizes things a bit differently:
//In AsyncTask
#Override
protected void onPreExecute() {
showProgressDialog(R.string.importing_pages);
}
#Override
public void onPostExecute(Boolean b) {
hideProgressDialog();
}
//In Activity
public void showProgressDialog(int msgResId) {
showProgressDialog(getString(msgResId));
}
public void showProgressDialog(String msg) {
mProgressDialog = ProgressDialogHelper.buildDialog(this, msg);
mProgressDialog.show();
}
public void hideProgressDialog() {
if(mProgressDialog != null)
mProgressDialog.dismiss();
}
//My progress dialog helper class:
public class ProgressDialogHelper {
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msgResId the resId for the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, int msgResId) {
return buildDialog(activity, activity.getApplicationContext().getString(msgResId));
}
/**
* Creates a generic progress dialog with the specified message
*
* #param activity the activity which hosts the dialog. This must be an activity, not a context.
* #param msg the message to display
* #return a progress dialog
*/
public static ProgressDialog buildDialog(Activity activity, String msg) {
ProgressDialog dialog;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
dialog = new ProgressDialog(new ContextThemeWrapper(activity, android.R.style.Theme_Holo_Dialog));
else
dialog = new ProgressDialog(activity);
dialog.setMessage(msg);
dialog.setCancelable(false);
return dialog;
}
}
You don't have to make a helper class if you don't want to, it's just how I organized it. The main idea here is that the progress dialog should be owned by the Activity instead of the AsyncTask.
Also, the context used must be the activity's, not getApplicationContext(). It looks like you have that part right though.
You can display Progress Dialogs using AsyncTasks. That's not a problem. I do it all the time. What may be the problem is the doInBackground() method. What do you have there?
I also generally nest the AsyncTasks within the Activity class, so that it can call other Activity class methods in the onPostExecute() method. Otherwise, in order for it to communicate back with your Activity you'll have to use something like a handler or static references.
public class TestActivity extends Activity {
private AsyncTask<Void, Void, ArrayList<String>> bgLoader;
private ArrayList<String> listOfStuff;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
listOfStuff = new ArrayList<String>();
textView = (TextView) findViewById(R.id.textView);
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
bgLoader = new MyAsyncTask(this, "Waiting...").execute();
}
private void resumeDoingStuff() {
try {
listOfStuff = bgLoader.get();
textView.setText("Your list has " + listOfStuff.size() + " items in it!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public class MyAsyncTask extends AsyncTask<Void, Void, ArrayList<String>> {
private ProgressDialog progressDialog;
private String message;
private Context ctx;
public MyAsyncTask(Context context, String message) {
this.ctx = context;
this.message = message;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(ctx);
progressDialog.setMessage(message);
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
ArrayList<String> retList = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
try {
retList.add("TEST STRING " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return retList;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
progressDialog.dismiss();
resumeDoingStuff();
}
}
}

Progress dialog doesn't update on an AsyncTask onProgressUpdate

I'm developing an Android 3.1 and above application.
I have this code to download some json data:
public class FormsListActivity extends ListActivity
{
private List<Form> mForms;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.formlist);
FormListAsyncTask formAsyncTask = new FormListAsyncTask(this);
formAsyncTask.execute("http://192.168.1.128/RestServiceImpl.svc/forms/");
}
private class FormListAsyncTask extends AsyncTask<String, Integer, List<Form>> {
private Context mContext;
private ProgressDialog loadingDialog;
FormListAsyncTask(Context context)
{
mContext = context;
loadingDialog = new ProgressDialog(mContext);
loadingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
loadingDialog.setMessage("Downloading. Please wait...");
loadingDialog.setCancelable(false);
loadingDialog.setMax(100);
loadingDialog.show();
}
#Override
protected List<Form> doInBackground(String... url)
{
Log.v("doInBackground", "retreiving forms");
return FormSpringController.LoadAll(url[0]);
}
// Just some example code to update your progress dialog
protected void onProgressUpdate(Integer... values)
{
Log.v("onProgressUpdate", "updating: " + ((int) ((values[0] / (float) values[1]) * 100)));
loadingDialog.setProgress((int) ((values[0] / (float) values[1]) * 100));
}
protected void onPostExecute(List<Form> forms)
{
if (forms != null)
{
ListActivity act = (ListActivity) mContext;
act.setListAdapter(new FormAdapter(act, R.layout.form_list_item, forms));
mForms = forms;
}
else
{
TextView errorMsg = (TextView)
((FormsListActivity) mContext).findViewById(R.id.formErrorMsg);
errorMsg.setText("Problem downloading forms. Please try again later.");
}
loadingDialog.dismiss();
}
}
}
Why loadingDialog's progress is not updated on onProgressUpdate?
I am not finding any publishProgress(); in your code.
call publishProgress() from your doInBackground() which call override onProgressUpdate() implicitly.

Is it possible to pass a fragment in a constructor?

I am trying to pass my Fragment to an ASyncTask class so that I can update a widget or two in the fragment once the task completes. Here's what I'm dealing with:
public class LoginFragment extends Fragment {
Button loginButton;
TextView loginErrorMsg;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.loginfragment, container, false);
}
public OnClickListener loginListener = new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("LoginF", "onclick");
ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Logging in...");
LoginTask loginTask = new LoginTask((Polling) getActivity(), progressDialog);
loginTask.execute();
}
};
And the LoginTask:
public class LoginTask extends AsyncTask<String, Void, Integer> {
private ProgressDialog progressDialog;
private Polling activity;
private int id = -1;
private JSONParser jsonParser;
private static String loginURL = "http://davidjkelley.net/android_api/";
private static String registerURL = "http://davidjkelley.net/android_api/";
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_NAME = "name";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
TextView loginErrorMsg = (EditText)activity.findViewById(R.id.loginErrorMsg);
EditText userName = (EditText)activity.findViewById(R.id.emailEditText);
EditText passwordEdit = (EditText)activity.findViewById(R.id.passEditText);
public LoginTask(Polling activity, ProgressDialog progressDialog)
{
this.activity = activity;
this.progressDialog = progressDialog;
}
So I would like to add a third parameter to the constructor of LoginTask, essentially an instance of my LoginFragment. My goal is to update either a TextView or put up a Toast on the screen to clarify whether login succeeds or fails: as right now, the user has no way of telling how the login proceeded. Ideas?
As curious says you don't want to be passing Fragments around (they have a 'link' to the activity which is a context and passing contexts is baaad)
You want to pass a small object that can help you call back from your Task to your Fragment.
I would also use an interface. Here's my example:
Fragment:
public class LoginFragment extends Fragment implements OnClickListener, OnLoginListener{
Button loginButton;
TextView loginErrorMsg;
private ProgressDialog progressDialog;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Logging in...");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_login, container, false);
loginButton = v.findViewById(R.id.button);
loginButton.setOnClickListener(this);
return v;
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button:
Log.v("LoginF", "onclick");
progressDialog.show();
LoginTask loginTask = new LoginTask(this);
loginTask.execute();
break;
default:
break;
}
}
#Override
public void onLoginSuccess() {
progressDialog.dismiss();
// Yayy
}
#Override
public void onLoginFailure() {
progressDialog.dismiss();
// Boo
}
}
The ASyncTask:
public class LoginTask extends AsyncTask<String, Void, Integer> {
private final OnLoginListener listener;
public interface OnLoginListener{
public void onLoginSuccess();
public void onLoginFailure();
}
public LoginTask(OnLoginListener listener) {
this.listener = listener;
}
#Override
protected Integer doInBackground(String... params) {
try{
// Something
} catch (SomeException e){
listener.onLoginFailure();
}
return null;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
listener.onLoginSuccess();
}
}
If you get your head around interfaces your world will open up and your code will look less like the amazon jungle and more like a well organised garden ;-)
I suggest you use a Callback interface for this purpose. It is generally not a good idea to pass in UI-specific (actually, context-specific) objects to an AsyncTask.
Here's what I suggest. With this approach, you don't even need to pass in your Fragment around.
Disclaimer: I have not actually tried running this code - just typed it off the top of my head. So it may not even compile - it is just intended to be a guide.
interface LoginCallback{
void onLoginSuccess();
void onLoginFailure();
}
//onCreate code
TextView loginErrorMsg = (EditText)activity.findViewById(R.id.loginErrorMsg);
EditText userName = (EditText)activity.findViewById(R.id.emailEditText);
EditText passwordEdit = (EditText)activity.findViewById(R.id.passEditText);
LoginTask loginTask = new LoginTask(new LoginCallback(){
#Override
protected void onLoginSuccess(){
//Update UI
}
#Override
protected void onLoginFailure(){
//Update UI
}
});
loginTask.execute();
//LoginTask code.
public class LoginTask extends AsyncTask<String, Void, Integer> {
LoginCallback callback;
ProgressDialog progressDialog;
public LoginTask(LoginCallback callback){
this.callback = callback;
#Override protected void onPreExecute(){
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Logging in...");
}
#Override
protected Integer doInBackground(String... params){
//Do you login logic here.
}
#Override
protected void onPostExecute(Integer result) {
progressDialog.dismiss();
if(loginSuccess){
callback.onLoginSuccess();
} else {
callback.onLoginFailure();
}
}
}
}

Categories

Resources