13

Apologies if this is a simple question but I am very new to this and still learning.

I have an app and when my users click the button to login after entering their details, it is crashing with android.os.NetworkOnMainThreadException I have discovered this is because I am performing a network operation on the main thread and to resolve I need to use AsyncTask, I am stuck however with the syntax.

Here is my code after the button is clicked, calls a function to connect and then parses json into sqlite db.

// Login button Click Event
    btnLogin.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            String email = inputEmail.getText().toString();
            String password = inputPassword.getText().toString();
            UserFunctions userFunction = new UserFunctions();
            JSONObject json = userFunction.loginUser(email, password);

            // check for login response
            try {
                if (json.getString(KEY_SUCCESS) != null) {
                    loginErrorMsg.setText("");
                    String res = json.getString(KEY_SUCCESS); 
                    if(Integer.parseInt(res) == 1){
                        // user successfully logged in
                        // Store user details in SQLite Database
                        DatabaseHandler db = new DatabaseHandler(getApplicationContext());
                        JSONObject json_user = json.getJSONObject("user");

                        // Clear all previous data in database
                        userFunction.logoutUser(getApplicationContext());
                        db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));                        

                        // Launch Dashboard Screen
                        Intent dashboard = new Intent(getApplicationContext(), DashboardActivity.class);

                        // Close all views before launching Dashboard
                        dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(dashboard);

                        // Close Login Screen
                        finish();
                    }else{
                        // Error in login
                        loginErrorMsg.setText("Incorrect username/password");
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });

How do I change this to the correct class ? I am not passing URL's etc. I think it needs to be something like this , but I am really struggling to get the syntax right.

Many thanks!!!

class login extends AsyncTask<Void, Void, Void> {

    private Exception exception;

    protected ??? doInBackground(???) {
        try {
Gary
  • 377
  • 1
  • 6
  • 22

1 Answers1

26

It would be something like this

   public class TalkToServer extends AsyncTask<Void, Void, Void> {

   @Override
   protected void onPreExecute() {
        /*
         *    do things before doInBackground() code runs
         *    such as preparing and showing a Dialog or ProgressBar
        */
   }

   @Override
   protected void onProgressUpdate(Void... values) {
        /*
         *    updating data
         *    such a Dialog or ProgressBar
        */

   }

   @Override
   protected Void doInBackground(Void... params) {
      //do your work here
      return null;
   }

   @Override
   protected void onPostExecute(Void result) {
        /*
         *    do something with data here
         *    display it or send to mainactivity
         *    close any dialogs/ProgressBars/etc...
        */
   }
}

Then you can execute it with

TalkToServer myTask = new MyTask(); // can add params for a constructor if needed
myTask.execute(); // here is where you would pass data to doInBackground()

You may not need onProgressUpdate() or onPreExecute() if you aren't using them to show a Dialog, progress, or other tasks before or during doInBackground().

onPreExecute() can be used to initialize and show a ProgressDialog. Then it could be dismissed in onPostExecute()

After a task finishes

onPostExecute() will be called. If the class is an inner-class of your Activity then you can update UI elements there or call a function to run code once the task finishes. If it is a separate file than the Activity then you can use an interface and create a callBack to the Activity and run code there once the task finishes.

This answer talks about using an interface for a callback if you need

Make sure any UI updating is done in any method besides doInBackground() or sent back to the Activity in any function besides doInBackground(). Heavy-lifting such as network operations should be done in doInBackground().

Also, be sure to read through the AsyncTask Docs completely. Especially the Threading Rules

Community
  • 1
  • 1
codeMagic
  • 44,549
  • 13
  • 77
  • 93
  • anyway just my 2 cents about `super.onPostExecute(...)`, `super.onProgressUpdate(...)` and `super.onPreExecute()` ... i've seen many examples where ppls call those in own implementation of AsyncTask ... i got a question: what for ... all those methods are empty in base/super class ... – Selvin Sep 19 '13 at 15:03
  • Thanks ... but I still have one error on public class TalkToServer extends AsyncTask --- Illegal modifier for the local class TalkToServer; only abstract or final is permitted – Gary Sep 19 '13 at 15:08
  • Is it declared outside of a method? And how are you initializing it? – codeMagic Sep 19 '13 at 15:10