2016-08-13 39 views
2

我是Android开发新手,我很难让listView与FirebaseDatabase一起工作。使用自定义适配器的ListView。按钮删除Firebase数据库中的子项

我有一个ListView,其中代表我的FirebaseDatabase中的一个对象的每个项目都有一个删除按钮。我想要做的是,当用户点击按钮时,从在线数据库中删除此条目。如果我没有弄错,那应该在包含ListView的Activity中触发onChildRemoved()回调方法,因此,我必须在那里更新ListView(已被照顾)

我试过在我的适配器中实现setOnClickListener,但我无法使它工作。你们中的一个人是否知道如何做到这一点?

问题:我使用push()方法将我的对象添加到数据库。由于需要删除对象的关键字,我认为向所述对象添加一个pushId成员是跟踪它的最简单的方法。我只想知道这个逻辑是否有意义。

如果这对你来说有点奇怪,请告诉我。我意识到我做这一切都是错误的可能性,我希望以正确的方式做到这一点!

+0

这里列出了多个问题。最好的做法是将你的问题分解成单独的帖子。您可以在ListView中拥有一个OnItemClickListener。用对象存储密钥是可以的。您也可以调用getKey来获取特定对象的密钥。 – dazza5000

回答

1

你的问题排序是一个小型的项目,但我做了一些代码,您希望帮助。

下面的代码构成了“thingy”对象的示例数组列表。 Thingy对象有一个名称(例如:box,toy,cat)和UID字段(使用您提及的您使用的push()方法生成)。然后将Thingy对象列表设置为FirebaseDatabase根节点(ref),其标签是其UID。虽然您可能已经编写了这些代码,但我们将使用此代码块作为示例。

// a root database reference 
    DatabaseReference ref = 
      FirebaseDatabase.getInstance().getReference().child("RootNode"); 

    // sample arraylist of objects 
    // Thingy objects have a type and UID field 
    ArrayList<Thingy> thingyList = new ArrayList(); 
    thingyList.add(new Thingy("box",ref.push().getKey())); 
    thingyList.add(new Thingy("toy",ref.push().getKey())); 
    thingyList.add(new Thingy("cat",ref.push().getKey())); 

    // set all Thingy objects in thingyList to your root node 
    // under the label that is the thingy's UID 
    for (Thingy x : thingyList) { 
     ref.child(x.getUID()).setValue(x); 
    } 

    // setup the adapter and listview 
    // R.id.remove_item is an xml layout that contains 
    //  a textview and a remove button 
    MyAdapter myAdapter = new MyAdapter(this, R.layout.remove_item, thingyList); 
    ListView myList = (ListView) findViewById(R.id.removeListView); 
    myList.setAdapter(myAdapter); 

然后才能使用您的适配器来使用删除按钮来删除您FirebaseDatabase的啄对象,你可以将一个onClickListener每个按钮为每个项目。然后使用remove()从数据库中完全删除该对象。

public class MyAdapter extends ArrayAdapter<ArrayList> { 
private Context context; 
private int resource; 
private ArrayList arrayList; 

private DatabaseReference ref = 
     FirebaseDatabase.getInstance().getReference().child("RootNode"); 


public MyAdapter(Context context, int resource, ArrayList arrayList) { 
    super(context, resource, arrayList); 
    this.context = context; 
    this.resource = resource; 
    this.arrayList = arrayList; 
} 

private static class ViewHolder { 
    TextView type; 
    Button removeButton; 
} 

@Override 
public View getView(int position, View convertView,ViewGroup parent) { 
    View row; 
    ViewHolder viewHolder; 
    if (convertView == null) { 
     viewHolder = new ViewHolder(); 
     LayoutInflater inflater = ((Activity) context).getLayoutInflater(); 
     row = inflater.inflate(resource, parent, false); 
     viewHolder.type = (TextView) row.findViewById(R.id.type); 
     viewHolder.removeButton = (Button) row.findViewById(R.id.removeButton); 
     row.setTag(viewHolder); 
    } else { 
     row = convertView; 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    final Thingy x = (Thingy) arrayList.get(position); 

    viewHolder.type.setText(x.getType()); 
    viewHolder.removeButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      ref.child(x.getUID()).removeValue(); 
     } 
    }); 
    return row; 
} 

将监听器附加到每个项目可能会很昂贵,因此如果您有大量对象,性能可能会下降。但是,这是在适配器中使用侦听器的实现,当您的列表视图项变得更加复杂时,使用适配器会变得棘手。所以,也许随着你学习越来越多的android,你可以找到一种更有效的方式来移除项目中的项目。

至于你的其他问题: 是的,onChildRemoved将被调用。但是,从onChildRemoved更新列表视图没有任何意义。如果用户删除一个项目,onClick应该做删除。至于访问相同数据库的其他用户,他们应该在应用程序尝试创建列表视图时简单地读取数据库。只有当您需要向所有其他用户发送某种类型的警报时,使用onChildRemoved才有意义。

使用push()是一种简单而安全的方式来创建唯一的ID(在我的代码中的UID),可以用来引用整个项目中的对象。尽管你可以使用继承来将对象从它们的UID中分离出来(拥有一个只保存id并在子类对象上使用setValue的父类),但我经常只是将UID包含在对象实例字段中,然后在发送它们时获取UID到数据库。

+0

首先,非常感谢这个代码示例,它绝对有帮助!但是,正如我明白为什么我不应该更新onChildRemoved的列表视图,这让我想知道我应该如何处理数据检索。每次用户转到包含ListView的活动时,是否应该使用addListenerForSingleValueEvent()来检索我的数据,并在本地处理其余部分?我还需要用户能够点击这些项目以获得更多关于它的信息,我是否错误地说过,使用这种方法,我还必须处理用户点击未知项目? – Nap

+0

如果你的活动没有生效,addListenerForSingleValueEvent()效果很好。如果你的活动是活的(听起来是这样的),使用小孩活动确实有意义,因为你实时“告诫”了其他用户,但它的成本更高,并且如果处理不好,可能会使UX变得粗糙。在这一点上,它更少的是什么是正确的,更多地使用你的自由裁量权什么是有效的,更有效。只要确保您的FirebaseDB树非常浅且轻便(例如:不要将图像存储在对象根节点下5层深处),否则您获取的对象的每个快照都将超载数据。 –

+0

好的,谢谢,它现在工作得很好! – Nap

0

首先将所有的firebase钥匙加入地图钥匙,然后根据钥匙全部获得所有的价值和显示列表。一旦删除调用onChildRemove()传递密钥,并且通知它,则它将从您的列表中删除。如果你想从firebase中删除只是传递null。可能下面的代码会帮助你。

@覆盖

public void onChildAdded(Object listenerId,String key,EventObject value) { 
    hashMapObject.put(key, value); 
    RecyclerViewAdapter adapter = (RecyclerViewAdapter) getAdapter(); 
    adapter.add(hashMapObject.size()-1, value); 
} 

@Override 
public void onChildChanged(Object listenerId, String key, EventObject value) { 
    int index = -1; 
    for(String _key : hashMapObject.keySet()){ 
     index++; 
     if(_key.equalsIgnoreCase(key)){ 
      hashMapObject.put(key, value); 
      RecyclerViewAdapter adapter = (RecyclerViewAdapter) getAdapter(); 
      adapter.update(index, value); 
      break; 
     } 
    } 
} 

@Override 
public void onChildRemoved(Object listenerId, String key) { 
    int index = -1; 
    for(String _key : hashMapObject.keySet()){ 
     index++; 
     if(_key.equalsIgnoreCase(key)){ 
      hashMapObject.remove(key); 
      RecyclerViewAdapter adapter = (RecyclerViewAdapter) getAdapter(); 
      adapter.remove(index); 
      break; 
     } 
    } 
} 
相关问题