Fragment 中的 ExpandableListView 在 AsyncTask 后未更新
ExpandableListView in Fragment not updating after AsyncTask
我正在尝试使用 4 个过滤器(组列表)实现 ExpandableListView:
这个可扩展列表位于片段中,因为我想使用 Master/Detail 流模式。
当用户点击过滤器时,AsyncTask 调用 Web 服务以获取点击过滤器的相关元素。然后,在 onPostExecute()
方法中,我更新了这个可扩展列表的 HashMap,然后,我执行了 notifySetDataChanged
方法,但是列表中没有数据出现:(
下面是代码的一些细节:
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();
}
});
}
}
}
我做错了什么?任何帮助将不胜感激!
问题出在 OnGroupClickListener()
方法上。覆盖此方法,collapseGroup
和expandGroup
方法不是运行,因此children的数据没有显示。
更改此方法后,它可以正常工作:
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;
}
});
我正在尝试使用 4 个过滤器(组列表)实现 ExpandableListView:
这个可扩展列表位于片段中,因为我想使用 Master/Detail 流模式。
当用户点击过滤器时,AsyncTask 调用 Web 服务以获取点击过滤器的相关元素。然后,在 onPostExecute()
方法中,我更新了这个可扩展列表的 HashMap,然后,我执行了 notifySetDataChanged
方法,但是列表中没有数据出现:(
下面是代码的一些细节:
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();
}
});
}
}
}
我做错了什么?任何帮助将不胜感激!
问题出在 OnGroupClickListener()
方法上。覆盖此方法,collapseGroup
和expandGroup
方法不是运行,因此children的数据没有显示。
更改此方法后,它可以正常工作:
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;
}
});