Firebase简单聊天客户端无法检索值

时间:2014-10-22 08:39:04

标签: java android firebase-realtime-database

我正在尝试构建基于firebase的最简单的android聊天应用程序,我已经从他们的android聊天示例中使用了firebase列表适配器来聊天。并使用了我自己的模型类,但该死的东西不起作用。这是课程和日志:

消息模型类:

import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;
import com.shaded.fasterxml.jackson.annotation.JsonIgnore;


public class Message {
    int messageId;
    String messageContent;

    // int chatID;
    // int senderID;
    // int recieverID;
    // Date timeStamp;
    // String messageType;

    /**
     * Message constructor to create message object
     * 
     * @param messageID
     * @param messageContent
     * @param chatID
     *            {@link Chat}
     * @param senderID
     *            {@link User}
     * @param recieverID
     *            {@link User}
     * @param messageType
     */
    // public Message(int messageID, String messageContent, int chatID,
    // int senderID, int recieverID, MessageType messageType) {
    // this.messageID = messageID;
    // this.messageContent = messageContent;
    // this.chatID = chatID;
    // this.senderID = senderID;
    // this.recieverID = recieverID;
    // this.messageType = messageType;
    // }

    @JsonIgnore
    public Message(int messageId, String messageContent) {
        // this.messageContent = messageContent;
        this.messageId = messageId;
        this.messageContent = messageContent;
    }

    /**
     * Message constructor to create message object This will be used when the
     * user send the message and still no status for this message
     * 
     * @param messageContent
     * @param chatID
     *            {@link Chat}
     * @param senderID
     *            {@link User}
     * @param recieverID
     *            {@link User}
     * @param messageType
     */
    // public Message(String messageContent, int chatID, int senderID,
    // int recieverID, MessageType messageType) {
    // this.messageContent = messageContent;
    // this.chatID = chatID;
    // this.senderID = senderID;
    // this.recieverID = recieverID;
    // this.messageType = messageType;
    // }

    /**
     * Message constructor to create message object from JSON response This
     * constructor will be used to create an object from web service JSON
     * response
     * 
     * @param message
     * @throws JSONException
     */
    // public Message(JSONObject message) throws JSONException {
    // messageID = message.getInt("messageID");
    // messageContent = message.getString("messageContent");
    // chatID = message.getInt("chatID");
    // senderID = message.getInt("senderID");
    // recieverID = message.getInt("recieverID");
    // messageType = MessageType.values()[message.getInt("messageType")];
    // }

    /**
     * 
     * @return messageID
     */
     public int getMessageId() {
     return messageId;
     }

     /**
     *
     * @param messageID
     */
     public void setMessageId(int messageId) {
     this.messageId = messageId;
     }

    /**
     * 
     * @return messageContent
     */
     public String getMessageContent() {
     return messageContent;
     }

    /**
     * 
     * @param messageContent
     */
     public void setMessageContent(String messageContent) {
     this.messageContent = messageContent;
     }

    /**
     * 
     * @return chatID
     */
    // public int getChatID() {
    // return chatID;
    // }
    //
    // /**
    // *
    // * @param chatID
    // */
    // public void setChatID(int chatID) {
    // this.chatID = chatID;
    // }

    /**
     * 
     * @return senderId
     */
//   public int getSenderId() {
//   return senderId;
//   }
    //
    // //
    // // /**
    // // *
    // // * @param senderID
    // // */
//   public void setSenderId(int senderId) {
//   this.senderId = senderId;
//   }

    /**
     * 
     * @return recieverID
     */
    // public int getRecieverID() {
    // return recieverID;
    // }
    //
    // /**
    // *
    // * @param recieverID
    // */
    // public void setRecieverID(int recieverID) {
    // this.recieverID = recieverID;
    // }

    /**
     * 
     * @return timeStamp
     */
    // public Date getTimeStamp() {
    // return timeStamp;
    // }
    //
    // /**
    // *
    // * @param timeStamp
    // */
    // public void setTimeStamp(Date timeStamp) {
    // this.timeStamp = timeStamp;
    // }

    /**
     * 
     * @return messageType
     */
//  public MessageType getMessageType() {
//      return messageType;
//  }
    //
    // /**
    // *
    // * @param messageType
    // */
    // public void setMessageType(MessageType messageType) {
    // this.messageType = messageType;
    // }

}

这是适配器类:

import android.app.Activity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import com.firebase.client.ChildEventListener;
import com.firebase.client.DataSnapshot;
import com.firebase.client.FirebaseError;
import com.firebase.client.Query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: greg
 * Date: 6/21/13
 * Time: 1:47 PM
 */

/**
 * This class is a generic way of backing an Android ListView with a Firebase location.
 * It handles all of the child events at the given Firebase location. It marshals received data into the given
 * class type. Extend this class and provide an implementation of <code>populateView</code>, which will be given an
 * instance of your list item layout and an instance your class that holds your data. Simply populate the view however
 * you like and this class will handle updating the list as the data changes.
 * @param <Message> The class type to use as a model for the data contained in the children of the given Firebase location
 */
public abstract class FirebaseListAdapter<Message> extends BaseAdapter {

private Query ref;
private Class<Message> modelClass;
private int layout;
private LayoutInflater inflater;
private List<Message> models;
private Map<String, Message> modelNames;
private ChildEventListener listener;


/**
 * @param ref The Firebase location to watch for data changes. Can also be a slice of a location, using some
 *            combination of <code>limit()</code>, <code>startAt()</code>, and <code>endAt()</code>,
 * @param modelClass Firebase will marshall the data at a location into an instance of a class that you provide
 * @param layout This is the layout used to represent a single list item. You will be responsible for populating an
 *               instance of the corresponding view with the data from an instance of modelClass.
 * @param activity The activity containing the ListView
 */
public FirebaseListAdapter(Query ref, Class<Message> modelClass, int layout, Activity activity) {
    this.ref = ref;
    this.modelClass = modelClass;
    this.layout = layout;
    inflater = activity.getLayoutInflater();
    models = new ArrayList<Message>();
    modelNames = new HashMap<String, Message>();
    // Look for all child events. We will then map them to our own internal ArrayList, which backs ListView
    listener = this.ref.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {

            Log.v("KK", "starded listener");
            Message model = dataSnapshot.getValue(FirebaseListAdapter.this.modelClass);
            modelNames.put(dataSnapshot.getName(), model);
            Log.v("KK", "faga3");

            // Insert into the correct location, based on previousChildName
            if (previousChildName == null) {
                models.add(0, model);
            } else {
                Message previousModel = modelNames.get(previousChildName);
                int previousIndex = models.indexOf(previousModel);
                int nextIndex = previousIndex + 1;
                if (nextIndex == models.size()) {
                    models.add(model);
                } else {
                    models.add(nextIndex, model);
                }
            }

            notifyDataSetChanged();
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            // One of the models changed. Replace it in our list and name mapping
            String modelName = dataSnapshot.getName();
            Message oldModel = modelNames.get(modelName);
            Message newModel = dataSnapshot.getValue(FirebaseListAdapter.this.modelClass);
            int index = models.indexOf(oldModel);

            models.set(index, newModel);
            modelNames.put(modelName, newModel);

            notifyDataSetChanged();
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

            // A model was removed from the list. Remove it from our list and the name mapping
            String modelName = dataSnapshot.getName();
            Message oldModel = modelNames.get(modelName);
            models.remove(oldModel);
            modelNames.remove(modelName);
            notifyDataSetChanged();
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {

            // A model changed position in the list. Update our list accordingly
            String modelName = dataSnapshot.getName();
            Message oldModel = modelNames.get(modelName);
            Message newModel = dataSnapshot.getValue(FirebaseListAdapter.this.modelClass);
            int index = models.indexOf(oldModel);
            models.remove(index);
            if (previousChildName == null) {
                models.add(0, newModel);
            } else {
                Message previousModel = modelNames.get(previousChildName);
                int previousIndex = models.indexOf(previousModel);
                int nextIndex = previousIndex + 1;
                if (nextIndex == models.size()) {
                    models.add(newModel);
                } else {
                    models.add(nextIndex, newModel);
                }
            }
            notifyDataSetChanged();
        }

        @Override
        public void onCancelled(FirebaseError arg0) {
            // TODO Auto-generated method stub

        }
    });
}

public void cleanup() {
    // We're being destroyed, let go of our listener and forget about all of the models
    ref.removeEventListener(listener);
    models.clear();
    modelNames.clear();
}

@Override
public int getCount() {
    return models.size();
}

@Override
public Object getItem(int i) {
    return models.get(i);
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    if (view == null) {
        view = inflater.inflate(layout, viewGroup, false);
    }

    Message model = models.get(i);
    // Call out to subclass to marshall this model into the provided view
    populateView(view, model);
    return view;
}

/**
 * Each time the data at the given Firebase location changes, this method will be called for each item that needs
 * to be displayed. The arguments correspond to the layout and modelClass given to the constructor of this class.
 *
 * Your implementation should populate the view using the data contained in the model.
 * @param v The view to populate
 * @param model The object containing the data used to populate the view
 */
protected abstract void populateView(View v, Message model);

}

最后这是log cat

    10-22 11:30:15.276: V/KK(14856): starded listener
10-22 11:30:15.296: D/AndroidRuntime(14856): Shutting down VM
10-22 11:30:15.296: W/dalvikvm(14856): threadid=1: thread exiting with uncaught exception (group=0x415b0ba8)
10-22 11:30:15.306: E/AndroidRuntime(14856): FATAL EXCEPTION: main
10-22 11:30:15.306: E/AndroidRuntime(14856): Process: ********, PID: 14856
10-22 11:30:15.306: E/AndroidRuntime(14856): com.firebase.client.FirebaseException: Failed to bounce to type
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:186)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at ******$1.onChildAdded(FirebaseListAdapter.java:66)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.firebase.client.core.ChildListenerContainer$1.run(ChildListenerContainer.java:49)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at android.os.Handler.handleCallback(Handler.java:733)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at android.os.Handler.dispatchMessage(Handler.java:95)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at android.os.Looper.loop(Looper.java:136)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at android.app.ActivityThread.main(ActivityThread.java:5017)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at java.lang.reflect.Method.invokeNative(Native Method)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at java.lang.reflect.Method.invoke(Method.java:515)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at dalvik.system.NativeStart.main(Native Method)
10-22 11:30:15.306: E/AndroidRuntime(14856): Caused by: com.shaded.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.annabsoft.androidapp.tilochatlibrary.models.Message] from String value; no single-String constructor/factory method
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.deser.std.StdValueInstantiator._createFromStringFallbacks(StdValueInstantiator.java:428)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:299)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1056)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:136)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:123)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.shaded.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
10-22 11:30:15.306: E/AndroidRuntime(14856):    at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:182)
10-22 11:30:15.306: E/AndroidRuntime(14856):    ... 12 more
10-22 11:35:15.466: I/Process(14856): Sending signal. PID: 14856 SIG: 9

2 个答案:

答案 0 :(得分:1)

只是为了使答案正式化,以便对搜索此内容的其他人有用:

使用DataSnapshot.getValue(YourModel.Class),您可以获得一个解析对象,其结构与Firebase中定义的相同。只需确保YourModel.class具有该结构。

将返回的对象序列化为POJO时,它必须包含与Firebase对象完全相同的属性。

答案 1 :(得分:0)

尝试在empty constructor中加入Pojo classMessage

Message () {
}