简体   繁体   中英

AsyncTask onPostExecute() is called before getting response from doInBackground() in android?

Here is my code:-

Goals.java class

public class Goals  extends AppCompatActivity{

    private ArrayList<Goal> result;
    private RecyclerView.Adapter adapter;
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private ArrayList<Goal> dataFromServer;
    private Toolbar toolbar;


    //This is for back button
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                startActivity(new Intent(this, MainActivity.class));
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.goal_list);

        recyclerView=(RecyclerView) findViewById(R.id.goal_recycler_view);
        toolbar=(Toolbar) findViewById(R.id.toolbar);


        recyclerView.setHasFixedSize(true);

        layoutManager=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        setSupportActionBar(toolbar);

        //FOr back button
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);


        //fetch goal list from server and also its related action
        getData();

        //Send Data to GoalAdaptor
        showData();

    }

    private void showData() {
        Log.i("Show Date","Enter");
        System.out.println("Result Array List"+result.toString());
        adapter=new goalAdaptor(this, result);
        recyclerView.setAdapter(adapter);
    }

    private void getData() {

        result=new ArrayList<>();

        DownloadPlansFromServer server= new DownloadPlansFromServer();
        server.execute();

    }


    class DownloadPlansFromServer extends AsyncTask<Void,Void,Boolean>
    {

        private ProgressDialog progressDialog;
        Boolean planActive=false;

        protected void onPreExecute() {
            // NOTE: You can call UI Element here.

            //UI Element
            progressDialog = new ProgressDialog(Goals.this);

            progressDialog.setMessage("Downloading Plans Data..");
            progressDialog.show();
        }


        @Override
        protected Boolean doInBackground(Void... params) {



            try {

                Response.Listener listener=new Response.Listener<JSONObject>()
                {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {

                            System.out.println("Inside the response");
                            // Parsing json object response
                            // response will be a json object

                            System.out.println("Output is "+response.toString());


                            //Toast.makeText(getApplicationContext(),response.toString(),Toast.LENGTH_LONG).show();

                            planActive=response.getBoolean("success");



                            if (planActive)
                            {
                                JSONArray plansArray=response.getJSONArray("response");

                                //get Plans Details
                                for (int p=0;p<plansArray.length();p++)
                                {
                                    JSONObject plan=plansArray.getJSONObject(p);

                                    //get Goals Details
                                    JSONObject planGoals=plan.getJSONObject("goal");

                                    Goal goal=new Goal();
                                    goal.setGoal_name("Goal Name:- "+planGoals.getString("goal_name"));

                                    Log.i("Goal Name is",planGoals.getString("goal_name"));

                                    JSONObject currentValue=planGoals.getJSONObject("current_value");
                                    JSONObject targetValue=planGoals.getJSONObject("target_value");

                                    //Get the values parameter
                                    ArrayList<String> parameterList=getTheParameter(planGoals.getString("goal_id"));

                                    if (parameterList.isEmpty())
                                    {
                                        System.out.println("Problem WHile Processing the parameter ");
                                    }
                                    else
                                    {
                                        String goalDescription="Reduce the value from";

                                        StringBuilder currentStringBuilder=new StringBuilder();

                                        for (int k=0;k<parameterList.size();k++)
                                        {
                                            currentStringBuilder.append(currentValue.getString(parameterList.get(k))+"/");
                                        }

                                        StringBuilder targetStringBuilder=new StringBuilder();

                                        for (int k=0;k<parameterList.size();k++)
                                        {
                                            targetStringBuilder.append(targetValue.getString(parameterList.get(k))+"/");

                                        }

                                        goal.setGoal_description(goalDescription+currentStringBuilder.toString()+" to "+ targetStringBuilder.toString());
                                    }

                                    //Add the result to the array
                                    result.add(goal);

                                }

                            }


                        }
                        catch (JSONException k)
                        {
                            Log.i("On Response",k.getMessage());
                            k.printStackTrace();
                        }

                    }
                };


                Response.ErrorListener errorListener=new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                        //   Handle Error
                        if (error instanceof TimeoutError || error instanceof NoConnectionError) {
                            error.printStackTrace();
                            Toast.makeText(getApplicationContext(), " this Network Error", Toast.LENGTH_SHORT).show();
                        } else if (error instanceof AuthFailureError) {
                            //TODO
                            error.printStackTrace();
                            Toast.makeText(getApplicationContext(), "User not authorized", Toast.LENGTH_SHORT).show();
                        } else if (error instanceof ServerError) {
                            //TODO
                            error.printStackTrace();
                            Toast.makeText(getApplicationContext(), "Server error", Toast.LENGTH_SHORT).show();
                        } else if (error instanceof NetworkError) {
                            //TODO
                            error.printStackTrace();
                            Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT).show();
                        } else if (error instanceof ParseError) {
                            //TODO
                            error.printStackTrace();
                            Toast.makeText(getApplicationContext(), "Error consuming request", Toast.LENGTH_SHORT).show();
                        }
                        else error.printStackTrace();
                    }
                };

                String plan_url=Constants.url+"plan";

                JsonObjectHeader customRequest=new JsonObjectHeader(plan_url,null, listener, errorListener);
                RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
                requestQueue.add(customRequest);

                System.out.println("After custom Request");

                planActive=true;

            }catch (Exception e)
            {
                e.printStackTrace();
            }


            return planActive;
        }


        protected void onPostExecute(Boolean unused) {
            // NOTE: You can call UI Element here.

            // Close progress dialog
            progressDialog.dismiss();

            if (unused)
            {
                Log.i("Get Plan","Yes");
                //showData();

            }

            else
                Toast.makeText(getApplicationContext(),"No Plans Found",Toast.LENGTH_LONG).show();

        }


    }

    private ArrayList<String> getTheParameter(String goal_id) {

        ArrayList<String> arrayList=new ArrayList<>();

        if (goal_id.equals("bp"))
        {
            arrayList.add("systolic");
            arrayList.add("diastolic");

            return arrayList;
        }
        else
        {
            arrayList.add(null);
            return arrayList;
        }



    }


}

The problem is:- Before getting the response from server, the onPostExecute() function executed. So I will get empty result arraylist.

JsonObjectHeader class is the basic volley class to fetch data from server.

No need to use async task while you want network call by using any third party library. because the volly create its own thread for network call.

If you are using volley library then remove AsyncTask and write this code in simple method

 try {

            Response.Listener listener=new Response.Listener<JSONObject>()
            {
                @Override
                public void onResponse(JSONObject response) {
                    try {

                        System.out.println("Inside the response");
                        // Parsing json object response
                        // response will be a json object

                        System.out.println("Output is "+response.toString());


                        //Toast.makeText(getApplicationContext(),response.toString(),Toast.LENGTH_LONG).show();

                        planActive=response.getBoolean("success");



                        if (planActive)
                        {
                            JSONArray plansArray=response.getJSONArray("response");

                            //get Plans Details
                            for (int p=0;p<plansArray.length();p++)
                            {
                                JSONObject plan=plansArray.getJSONObject(p);

                                //get Goals Details
                                JSONObject planGoals=plan.getJSONObject("goal");

                                Goal goal=new Goal();
                                goal.setGoal_name("Goal Name:- "+planGoals.getString("goal_name"));

                                Log.i("Goal Name is",planGoals.getString("goal_name"));

                                JSONObject currentValue=planGoals.getJSONObject("current_value");
                                JSONObject targetValue=planGoals.getJSONObject("target_value");

                                //Get the values parameter
                                ArrayList<String> parameterList=getTheParameter(planGoals.getString("goal_id"));

                                if (parameterList.isEmpty())
                                {
                                    System.out.println("Problem WHile Processing the parameter ");
                                }
                                else
                                {
                                    String goalDescription="Reduce the value from";

                                    StringBuilder currentStringBuilder=new StringBuilder();

                                    for (int k=0;k<parameterList.size();k++)
                                    {
                                        currentStringBuilder.append(currentValue.getString(parameterList.get(k))+"/");
                                    }

                                    StringBuilder targetStringBuilder=new StringBuilder();

                                    for (int k=0;k<parameterList.size();k++)
                                    {
                                        targetStringBuilder.append(targetValue.getString(parameterList.get(k))+"/");

                                    }

                                    goal.setGoal_description(goalDescription+currentStringBuilder.toString()+" to "+ targetStringBuilder.toString());
                                }

                                //Add the result to the array
                                result.add(goal);

                            }

                        }


                    }
                    catch (JSONException k)
                    {
                        Log.i("On Response",k.getMessage());
                        k.printStackTrace();
                    }

                }
            };


            Response.ErrorListener errorListener=new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                    //   Handle Error
                    if (error instanceof TimeoutError || error instanceof NoConnectionError) {
                        error.printStackTrace();
                        Toast.makeText(getApplicationContext(), " this Network Error", Toast.LENGTH_SHORT).show();
                    } else if (error instanceof AuthFailureError) {
                        //TODO
                        error.printStackTrace();
                        Toast.makeText(getApplicationContext(), "User not authorized", Toast.LENGTH_SHORT).show();
                    } else if (error instanceof ServerError) {
                        //TODO
                        error.printStackTrace();
                        Toast.makeText(getApplicationContext(), "Server error", Toast.LENGTH_SHORT).show();
                    } else if (error instanceof NetworkError) {
                        //TODO
                        error.printStackTrace();
                        Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT).show();
                    } else if (error instanceof ParseError) {
                        //TODO
                        error.printStackTrace();
                        Toast.makeText(getApplicationContext(), "Error consuming request", Toast.LENGTH_SHORT).show();
                    }
                    else error.printStackTrace();
                }
            };

            String plan_url=Constants.url+"plan";

            JsonObjectHeader customRequest=new JsonObjectHeader(plan_url,null, listener, errorListener);
            RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
            requestQueue.add(customRequest);

because in volley you can get response in onResponse so add onPostExecute inside this

Your issue is that you are creating an additional thread in your onBackground(Void...) .

Your code sees:

  1. Start onPreExecute.
  2. Show Dialog.
  3. Return from onPreExecute.
  4. Start onBackground.
  5. New thread created by Volley Request (Thread #2)
  6. Return from onBackground.
  7. Start onPostExecute.
  8. Close Dialog.
  9. Return from onPostExecute.
  10. Return from Thread #2.

You need to use a blocking method from the Volley system. This answer explains it.

RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(Method.POST, SIGNUP_URL, reqBody, future, future)
volleyRequestQueue.add(request);

try {
    JSONObject response = future.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}

It's not your postExecute it's your

showData();

is executed before

getData();

is complete. Ideally move your showData code to your postExecute and you will get your results as expected.

Remove the AsyncTask.

Move all code from doInBackgroud in a normal function.

Call showSata() in onResponse().

I think you should read articles where is a good explanation why you should not have to use AsyncTask. My suggestion is start using Retrofit (for working with Http) + You do not have to parse JSON on your own, you can use @SerializedName annotation in your Response object

Here's a tutorial demonstrates how to fetch data from server and fill recycle view

Here is my code for signing in

Call<LoginResponse> call = retrofit.create(ComeAroundAPIInterface.class).signin(data);
    call.enqueue(new Callback<LoginResponse>() {
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
            if (response.isSuccessful()) {               
                onLoginSuccess();
                sharedPreferences = getSharedPreferences(LOGIN_COOKIE, Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean("LOGIN",true);
                editor.commit();
                progressDialog.dismiss();
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                intent.putExtra("user", (LoginResponse)response.body());
                startActivity(intent);
                finish();
            } else {
                progressDialog.cancel();
                onLoginFailed();
                Converter<ResponseBody, APIError> converter = retrofit.responseBodyConverter(APIError.class, new Annotation[0]);
                APIError error = new APIError();
                try {error = converter.convert(response.errorBody());} catch (IOException e) {}
                Toast.makeText(getBaseContext(),error.message(),Toast.LENGTH_SHORT).show();
            }
        }
        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) {
            onLoginFailed();
            Log.e("Login", t.toString());
        }
    });

and here is my Response class with @SerializedName annotation

public class LoginResponse implements Parcelable{
    @SerializedName("id")
    private String id;
    @SerializedName("username")
    private String username;
    @SerializedName("email")
    private String email;
    @SerializedName("name")
    private String name;
    @SerializedName("sirname")
    private String sirname;

    //getters 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM