0

I am trying to update the UI of a fragment after executing an asynctask.

Here is what I do:

public class OpinionFragment extends Fragment {

    private static final String BUNDLE_POSTTION = "opinion_position";
    private static final String BUNDLE_OPINION_TEXT = "opinion_text";
    private CirclePulseView circlePulseView;
    private TextView opinionTV;
    private String opinionText;

    public static OpinionFragment newInstance(int position, String opinionText) {
        Bundle args = new Bundle();
        //add parameters to the bundle here
        //args.putInt(BUNDLE_OBJECTIVE_ID, objective.getLocalId());
        args.putInt(BUNDLE_POSTTION, position);
        args.putString(BUNDLE_OPINION_TEXT, opinionText);

        OpinionFragment fragment = new OpinionFragment();
        fragment.setArguments(args);

        return fragment;
    }

    public OpinionFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
            opinionText = args.getString(BUNDLE_OPINION_TEXT);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_opinion, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        opinionTV = (TextView) view.findViewById(R.id.opinionTV);
        opinionTV.setText(opinionText);
        circlePulseView = (CirclePulseView) view.findViewById(R.id.circle_view);
    }

    public void translateReview(String text) {
        if (text != null) {
            new TranslateReviewAsyncTask(text).execute();
        }
    }

    class TranslateReviewAsyncTask extends AsyncTask<Void, Void, String> {

        private String textToTranslate;

        public TranslateReviewAsyncTask(String textToTranslate) {
            this.textToTranslate = textToTranslate;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            circlePulseView.setVisibility(View.VISIBLE);
            opinionTV.setVisibility(View.GONE);
        }

        @Override
        protected String doInBackground(Void... params) {
            String result;
            HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, Constants.TIMEOUT_MILISEC);
            HttpConnectionParams.setSoTimeout(httpParams, Constants.TIMEOUT_MILISEC);
            HttpParams p = new BasicHttpParams();
            // Instantiate an HttpClient
            HttpClient httpclient = new DefaultHttpClient(p);
            String textParam = null;
            try {
                textParam = URLEncoder.encode(textToTranslate, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            String url = "http://192.168.0.104:8080/ClujTouristWS/webresources/tourists/translate/" + textParam;
            HttpGet httpGet = new HttpGet(url);

            // Instantiate a GET HTTP method
            try {
                Log.i(getClass().getSimpleName(), "send  task - start");
                ResponseHandler<String> responseHandler = new BasicResponseHandler();
                String responseBody = httpclient.execute(httpGet,
                        responseHandler);
                Log.d(LoginTouristAsyncTask.class.getCanonicalName(), "Login response: " + responseBody);
                result = responseBody;
            } catch (ClientProtocolException e) {
                e.printStackTrace();
                result = "error";
            } catch (IOException e) {
                e.printStackTrace();
                result = "error";
            }
            return result;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s != null && !s.equals("error")) {
                System.out.println("This is your translated text:  " + s);
            }
            circlePulseView.setVisibility(View.GONE);
            opinionTV.setVisibility(View.VISIBLE);
            opinionTV.setText(s);
        }
    }

}

I am trying to do this after pressing a button in the parent fragment:

translateTV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OpinionFragment fragment = (OpinionFragment) opinionsAdapter.getItem(currentPage);
                fragment.translateReview(opinionsAdapter.getObjectiveReviews().get(currentPage));
            }
        });

My code crashes here, onPreExecute

@Override
        protected void onPreExecute() {
            super.onPreExecute();
            circlePulseView.setVisibility(View.VISIBLE);
            opinionTV.setVisibility(View.GONE);
        }

saying that mCirclePulseView is null.... and i have no idea how I could fix this....

There is no other suitable time to fire the AsyncTask because: What I have is a Fragment with a viewPager with fragments and 2 buttons outside the view pager. Only after a button from the main fragment is pressed I should update the contents of the current fragment inside the pager...

This is my adapter class for the View Pager:

public class OpinionPagerAdapter extends FragmentStatePagerAdapter {

List<String> objectiveReviews = new ArrayList<String>();
private Map<Integer, Fragment> mPageReferenceMap = new HashMap<Integer,Fragment>();

public OpinionPagerAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public Fragment getItem(int position) {
    Fragment fragment = OpinionFragment.newInstance(position,objectiveReviews.get(position));
    mPageReferenceMap.put(position, fragment);
    return fragment;
}

@Override
public int getCount() {
    return objectiveReviews.size();
}

public void addOpinionsToList(List<String> objectiveReviews){
    this.objectiveReviews.clear();
    for (String o : objectiveReviews) {
        //if (CategoryUtils.getInstance().checkCategorySelected(o.getCategoryID())) {
        this.objectiveReviews.add(o);
        //}
    }
    notifyDataSetChanged();
}

public List<String> getObjectiveReviews(){
    return this.objectiveReviews;
}

public Fragment getFragment(int key){
    return mPageReferenceMap.get(key);
}

}

Adrian Olar
  • 2,883
  • 4
  • 35
  • 63
  • @Luksprog, the other question has been deleted. – matiash Jun 07 '14 at 07:17
  • Please don't delete your questions when they are clearly duplicates. Regarding your issue: this question has been asked a lot. You may want to post the adapter of the `ViewPager`. Most likely, in the `getItem()` method of the adapter you're just instantiating the page fragments so when you call `getItem()` in that click listener you end up with a new fragment that isn't attached to the activity(so it doesn't have its UI built, hence the exception). I was going to post this on your other initial question http://stackoverflow.com/questions/7379165/update-data-in-listfragment-as-part-of-viewpager – user Jun 07 '14 at 07:18
  • I deleted my previous question because I tried something different this time, I should have edited that one instead, so my bad... Thanks for your answer though – Adrian Olar Jun 07 '14 at 07:24
  • @Luksprog. The problem is that he's firing the AsyncTask too soon -- after creating the Fragment, but before onCreateView() has run. I think the answer you linked is for a different case (finding the fragment itself in the layout)... but I might be mistaken. – matiash Jun 07 '14 at 07:25
  • @matiash I've reopened the question as I might rushed in to it. In the code posted, he fires the task on a click listener after presumably getting the fragment from the `ViewPager`(so the UI should be available). @AdrianOlar Am I right about your `getItem()` method in the adapter of the `ViewPager`? Also, keep in mind that the `ViewPager` has available only the views of the current visible fragment + one on each side of the visible fragment(other fragments will have no view). – user Jun 07 '14 at 07:32
  • @Luksprog I have updated the question with my adapter... It seems to be true that the fragment does not get the chance to instantiate but I really don't understand why... Because the fragments are there, are inflated, I can swipe through them, however after clicking the button those elements are null in the asyncTask... – Adrian Olar Jun 07 '14 at 07:38
  • @Luksprog Looks like you were right after all. My bad :) – matiash Jun 07 '14 at 07:43
  • @Luksprog you are right, I am always returning a new fragment on the getItem() method but I am not quite sure how to avoid this... – Adrian Olar Jun 07 '14 at 07:43
  • I've linked above to a question where you can see a quick dirty method to access the real fragments used by the `ViewPager`(by a special tag used in the implementation). If you don't like that method the adapter will actually provide the fragments that it uses in the `instantiateItem()` method. If you override that method and keep references to what it returns(fragments) those will be the fragments that you're looking for(and we can later use it to do what you want). @matiash You made a sound assumption about a possible solution, there's nothing wrong with that. – user Jun 07 '14 at 07:50
  • Check my updated adapter, i get the same error however.... – Adrian Olar Jun 07 '14 at 08:06
  • Use `static private CirclePulseView circlePulseView;` – VenomVendor Jun 07 '14 at 08:10
  • @Luksprog I also tried `OpinionFragment fragment = (OpinionFragment) opinionsAdapter.instantiateItem(opinionsPager,currentPage);` and still the same error... – Adrian Olar Jun 07 '14 at 08:14
  • Ok, but did you changed the `OnClickListener` so that instead of `OpinionFragment fragment = (OpinionFragment) opinionsAdapter.getItem(currentPage);` you call `OpinionFragment fragment = (OpinionFragment) opinionsAdapter.getFragment(currentPage);` ? @VenomVendor that's not a good idea. – user Jun 07 '14 at 08:25

0 Answers0