Reputation: 36020
I am trying to build a dialog like this(google map layer choose dialog):
And this is my core codes:
public class MapLayerSourceChooseDialog extends DialogFragment {
private MapLayerSelectedListener mListener;
private LayerAdapter mLayerAdapter;
public void setLayerSelectListener(MapLayerSelectedListener listener) {
mListener = listener;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLayerAdapter = new LayerAdapter(getActivity(), R.layout.common_dialog_maplayer, new ArrayList<MapLayer>());
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Layers").setAdapter(mLayerAdapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (mListener != null) {
MapLayer layer = mLayerAdapter.getItem(which);
mListener.OnMapLayerSelected(which, layer);
}
}
});
Log.d("map", "dialog on create");
return builder.create();
}
public void updateData(List<MapLayer> layers) {
mLayerAdapter.updateItems(layers);
}
private class LayerAdapter extends ArrayAdapter<MapLayer> {
private List<MapLayer> mItems;
public LayerAdapter(Context context, int resource, List<MapLayer> items) {
super(context, resource, items);
mItems = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null || convertView.getTag() == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.common_dialog_maplayer, parent, false);
holder = new ViewHolder();
holder.iconView = (ImageView) convertView.findViewById(R.id.map_layer_icon);
holder.nameView = (TextView) convertView.findViewById(R.id.map_layer_name);
holder.checkView = (ImageView) convertView.findViewById(R.id.map_layer_check);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
MapLayer layer = getItem(position);
holder.iconView.setImageDrawable(getResources().getDrawable(layer.drawable));
holder.nameView.setText(layer.name);
holder.checkView.setVisibility(layer.isActive ? View.VISIBLE : View.GONE);
return convertView;
}
public void updateItems(List<MapLayer> layers) {
mItems.clear();
mItems.addAll(layers);
// notifyDataSetChanged();
}
}
private static class ViewHolder {
ImageView iconView;
TextView nameView;
ImageView checkView;
}
interface MapLayerSelectedListener {
void OnMapLayerSelected(int index, String name);
}
}
caller(at another activity):
mapLayerSourceChooseDialog.updateData(layers);
mapLayerSourceChooseDialog.show(getSupportFragmentManager(), null);
But I always get the NPE, I wonder if I use the dialog in a wrong way?
Can anyone check it for me ?
Upvotes: 0
Views: 168
Reputation: 45493
The problem is that you're assuming mLayerAdapter
will have been initialised by the time you call mapLayerSourceChooseDialog.updateData(layers)
. That's not correct. After you instantiate MapLayerSourceChooseDialog
, onCreate()
will not be called immediately.
Two obvious options:
List<MapLayer>
as argument to the fragment. Use the setArguments()
and getArguments()
methods on MapLayerSourceChooseDialog
. Your MapLayar
objects will have to be at least Serializable
, but preferably implement Parcelable
. Note that you probably don't want to go down this path if your objects are fairly complex and/or the size of the list is reasonably large.List<MapLayer>
, which the Activity
hosting the fragment should implement. In MapLayerSourceChooseDialog
you can then cast the activity and call the getter to retrieve the data. This approach could be faster to implement but may break if your activity doesn't correctly retain the List<MapLayer>
on configuration changes.An example of both approaches can be found in the documentation for DialogFragment
.
Upvotes: 1