Reputation: 241
I've implemented an ExpandableListAdapter
, and it's working fine apparently. Except that when the activity resumes, the child nodes get repeated. I don't know how to fix this, I've searched online for this and found nothing helpful.
I've mitigated the problem adding some != null
checks. Thus avoiding the insertion and creation of new data when not needed. But that hasn't fixed the problem.
Here's the CustomAdapter
public class ContatoAdapter extends BaseExpandableListAdapter {
private final Activity context;
private final Map<String, List<Contato>> contatosCollection;
private final List<String> area;
public ContatoAdapter(Activity context, List<String> area, Map<String, List<Contato>> contatosCollection) {
this.context = context;
this.contatosCollection = contatosCollection;
this.area = area;
}
@Override
public int getGroupCount() {
return area.size() ;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.contatosCollection.get(area.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPosition) {
return this.area.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.contatosCollection.get(this.area.get(groupPosition)).get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return this.area.get(groupPosition).hashCode();
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return this.contatosCollection.get(this.area.get(groupPosition)).get(childPosition).hashCode();
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String s = (String) getGroup(groupPosition);
final LayoutInflater gInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null){
convertView = gInflater.inflate(R.layout.group_item, parent, false);
}
final TextView item = (TextView) convertView.findViewById(R.id.list_header);
item.setText(s);
item.setTypeface(null, Typeface.BOLD);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final Contato contato = (Contato) getChild(groupPosition, childPosition);
final LayoutInflater cInflater = this.context.getLayoutInflater();
if (convertView == null){
convertView = cInflater.inflate(R.layout.list_item, parent, false);
}
TextView item = (TextView) convertView.findViewById(R.id.list_item_nome);
ImageView ver = (ImageView) convertView.findViewById(R.id.list_item_ver);
ver.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context.getApplicationContext(), DetalheActivity.class);
intent.putExtra("contato", contato);
context.startActivity(intent);
}
});
item.setText(contato.getNome());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
Here's the activity that has the listView
with the adapter:
public class MedicosActivity extends AppCompatActivity {
private ExpandableListView listView;
private ArrayList<Contato> contatos;
private ArrayList<String> areas;
private HashMap<String, List<Contato>> contatosCollection;
private ContatoAdapter adapter;
String jsonString = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_medicos);
setTitle("Médicos | Etc");
init();
if (listView == null)
listView = (ExpandableListView) findViewById(android.R.id.list);
adapter = new ContatoAdapter(this,areas,contatosCollection);
listView.setAdapter(adapter);
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Contato selected = (Contato) adapter.getChild(groupPosition,childPosition);
Toast.makeText(MedicosActivity.this, selected.getNome() , Toast.LENGTH_SHORT).show();
return true;
}
});
}
private void init() {
if (jsonString.isEmpty())
jsonString = JsonUtil.loadJSON(MedicosActivity.this, "data.json");
if (contatosCollection == null)
contatos = JsonUtil.parseJSON(jsonString);
if (areas == null){
areas = new ArrayList<>();
createGroupList();
}
if (contatosCollection == null){
contatosCollection = new HashMap<>();
createCollection();
}
}
private void createGroupList() {
for(Contato c : contatos){
if (!areas.contains(c.getArea())){
areas.add(c.getArea());
}
}
}
private void createCollection() {
for (Contato c : contatos){
List<Contato> ctg = contatosCollection.get(c.getArea());
if (ctg == null){
ctg = new ArrayList<>();
contatosCollection.put(c.getArea(), ctg);
}
ctg.add(c);
}
}
}
Adding the JSON
Parser class that caused the error:
private static ArrayList<Contato> contatoList = new ArrayList<>();
public static ArrayList<Contato> parseJSON(String jsonString){
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.optJSONArray("medicos");
for (int i = 0; i < jsonArray.length(); i++){
JSONObject medicoObj = jsonArray.getJSONObject(i);
JSONObject end = medicoObj.getJSONObject("endereco");
JSONArray coord = end.getJSONArray("coord");
LatLng latLng = new LatLng(coord.getDouble(0), coord.getDouble(1));
JSONArray telefones = medicoObj.getJSONArray("telefone");
String[] tels = new String[telefones.length()];
for (int j = 0; i < telefones.length(); i++) {
tels[i] = telefones.get(i).toString();
}
Contato c = new Contato(
medicoObj.getString("area")
, medicoObj.getString("nome")
, end.getString("rua")
, Integer.parseInt(end.getString("numero"))
, end.getString("complemento")
, tels
, latLng
);
contatoList.add(c);
}
return contatoList;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Upvotes: 1
Views: 402
Reputation: 241
Thanks to Liquid Penguin comment i was able to detect the problem. Since i was looking into the Adapter
class for problems i wasn't noticing the repeated data coming from the JSON parser
class.
It wasn't checking for duplicate data when getting data from the JSON
to the array. Here comes the fixed parser code
with the required verifications:
private static ArrayList<Contato> contatoList = new ArrayList<>();
public static ArrayList<Contato> parseJSON(String jsonString){
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.optJSONArray("medicos");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject medicoObj = jsonArray.getJSONObject(i);
if (medicoObj.length() != contatoList.size()) {
JSONObject end = medicoObj.getJSONObject("endereco");
JSONArray coord = end.getJSONArray("coord");
LatLng latLng = new LatLng(coord.getDouble(0), coord.getDouble(1));
JSONArray telefones = medicoObj.getJSONArray("telefone");
String[] tels = new String[telefones.length()];
for (int j = 0; i < telefones.length(); i++) {
tels[i] = telefones.get(i).toString();
}
Contato c = new Contato(
medicoObj.getString("area")
, medicoObj.getString("nome")
, end.getString("rua")
, Integer.parseInt(end.getString("numero"))
, end.getString("complemento")
, tels
, latLng
);
if (!contatoList.contains(c))
contatoList.add(c);
}
}
return contatoList;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Upvotes: 1