Home » Android » ExpandableListView in Fragment not updating after AsyncTask

ExpandableListView in Fragment not updating after AsyncTask

Posted by: admin November 1, 2017 Leave a comment

Questions:

I’m trying to implement an ExpandableListView with 4 filters (group list):

Expandable list

This expandable list it’s on a Fragment because I want to use the Master/Detail Flow pattern.

When user clicks on a filter, a web service is called by an AsyncTask to get associated elements of clicked filter. Then, in onPostExecute() method, I update the HashMap of this expandable list, and then, I execute the notifySetDataChanged method, but no data appear on the list 🙁

Here are some details of code:

TreatmentExpandableListAdapter.java

public class TreatmentExpandableListAdapter extends BaseExpandableListAdapter {

private Context context;
private List<TreatmentState> treatmentStates;
private HashMap<TreatmentState, List<TreatmentSummary>> treatmentsByState;
private TreatmentExpandableListAdapter adapter;

...

@Override
public View getGroupView(int groupPosition, boolean b, View view, ViewGroup viewGroup) {
    currentState = treatmentStates.get(groupPosition);
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.group_item,
                null);
    }
    TextView item = (TextView) view.findViewById(R.id.treatment_state);
    item.setTypeface(null, Typeface.BOLD);
    item.setText(currentState.toString());

    return view;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) {
    final TreatmentState state = treatmentStates.get(groupPosition);
    final TreatmentSummary treatment = (TreatmentSummary) getChild(groupPosition, childPosition);
    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if (view == null) {
        view = inflater.inflate(R.layout.fragment_treatment, null);
    }

    ImageView mStateView = (ImageView) view.findViewById(R.id.state);
    TextView mMedicineView = (TextView) view.findViewById(R.id.medicineName);
    TextView mInitDateView = (TextView) view.findViewById(R.id.initDate);
    TextView mEndDateView = (TextView) view.findViewById(R.id.endDate);

    mStateView.setImageResource(getImageByState(state));
    mMedicineView.setText(treatment.getMedicineName());
    mInitDateView.setText(treatment.getInitDate());
    mEndDateView.setText(treatment.getEndDate());

    return view;
}

...

TreatmentListFragment.java

public class TreatmentListFragment extends Fragment {

/* Parameter arguments, fragment initialization parameters */
private static final String PATIENT_ID = "patiendId";

/* Parameters */
private int mColumnCount = 1;
private long patientId;

ExpandableListView expListView;
TreatmentExpandableListAdapter expListAdapter;
List<TreatmentState> states;

/**
 * Mandatory empty constructor for the fragment manager to instantiate the
 * fragment (e.g. upon screen orientation changes).
 */
public TreatmentListFragment() {
}

@SuppressWarnings("unused")
public static TreatmentListFragment newInstance(long patientId) {
    TreatmentListFragment fragment = new TreatmentListFragment();
    Bundle args = new Bundle();
    args.putLong(PATIENT_ID, patientId);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getArguments() != null) {
        patientId = getArguments().getLong(PATIENT_ID);
    }
    states = Arrays.asList(TreatmentState.values());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_treatment_list, container, false);

    expListView = (ExpandableListView) view.findViewById(R.id.treatment_list);
    expListAdapter = new TreatmentExpandableListAdapter(
            view.getContext(), states, DiaryAppHelper.getTreatmentsByState());
    expListView.setAdapter(expListAdapter);
    expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long id) {

            TextView tv = (TextView) view.findViewById(R.id.treatment_state);

            TreatmentState state = TreatmentState.getEnumByNameState(tv.getText().toString());
            new GetTreatmentsTask().execute(state.name());

            return true;
        }
    });

    return view;
}


@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnListFragmentInteractionListener) {
        mListener = (OnListFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnListFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}


/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p/>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnListFragmentInteractionListener {
    // TODO: Update argument type and name
    void onListFragmentInteraction(TreatmentSummary treatment);
}
 ...
}

GetTreatmentsTask

private class GetTreatmentsTask extends AsyncTask<String, Void, TreatmentSummary[]> {
    @Override
    protected TreatmentSummary[] doInBackground(String... params) {
        try {
            final String uri = getContext().getString(R.string.baseURL) + "/treatments_state?patientId=" + DiaryAppHelper.getCurrentUser().getUserAccountId() + "&state=" + params[0];

            RestTemplate rt = new RestTemplate();
            rt.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

            ResponseEntity<TreatmentSummary[]> response = rt.getForEntity(uri, TreatmentSummary[].class);
            TreatmentSummary[] treatmentSummaries = response.getBody();

            return treatmentSummaries;
        } catch (Exception e) {
            Log.e("TreatmentExpandableList", e.getMessage(), e);
        }

        return null;
    }

    @Override
    protected void onPostExecute(TreatmentSummary[] treatmentSummariesArr) {
        if (treatmentSummariesArr != null && treatmentSummariesArr.length > 0) {
            TreatmentState state = treatmentSummariesArr[0].getState();
            Collections.addAll(expListAdapter.getTreatmentsByState().get(state), treatmentSummariesArr);


            getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    expListAdapter.notifyDataSetChanged();
                }
            });

        }

    }

}

What am I doing wrong? Any help would be appreciated!

Answers:

The problem was on OnGroupClickListener() method. Overwriting this method, collapseGroup and expandGroup methods were not running, therefore the data of the children was not displayed.

After changing this method, it works correctly:

expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long id) {

            TextView tv = (TextView) view.findViewById(R.id.treatment_state);

            TreatmentState state = TreatmentState.getEnumByNameState(tv.getText().toString());
            if (expandableListView.isGroupExpanded(groupPosition)) {
                expandableListView.collapseGroup(groupPosition);
            } else {
                new GetTreatmentsTask().execute(state.name());
                expandableListView.expandGroup(groupPosition);
            }

            return true;
        }
    });