获取 "Failed to bounce to type"

Getting "Failed to bounce to type"

我在使用 firebase 构建 android 聊天应用程序时遇到错误。当我发送消息时没问题,但发送消息后我收到错误消息。错误如下所示。

04-17 15:21:54.242 12961-12961/learning.firebase.app.learningfirebase E/AndroidRuntime: FATAL EXCEPTION: main
    com.firebase.client.FirebaseException: Failed to bounce to type
        at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:183)
        at learning.firebase.app.learningfirebase.FirebaseListAdapter.onChildAdded(FirebaseListAdapter.java:63)
        at com.firebase.client.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:48)
        at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
        at com.firebase.client.core.view.EventRaiser.run(EventRaiser.java:38)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:5365)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class learning.firebase.app.learningfirebase.Chat]: can not instantiate from JSON object (need to add/enable type information?)
     at [Source: java.io.StringReader@42285cd8; line: 1, column: 2]
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
        at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:181)
            ... 13 more

我的MainActivity.java

public class MainActivity extends ListActivity {
    private static final String FIREBASE_URL = "https://bohrachat.firebaseio.com/";

    private String mUsername;
    private Firebase mFirebaseRef;
    private ValueEventListener mConnectedListener;
    private ChatListAdapter mChatListAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupUsername();

        setTitle("Chatting as " + mUsername);

        // Setup our Firebase mFirebaseRef
        mFirebaseRef = new Firebase(FIREBASE_URL).child("chat");

        // Setup our input methods. Enter key on the keyboard or pushing the send button
        EditText inputText = (EditText) findViewById(R.id.messageInput);
        inputText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
                if (actionId == EditorInfo.IME_NULL && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
                    sendMessage();
                }
                return true;
            }
        });

        findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendMessage();
            }
        });

    }
    @Override
    public void onStart() {
        super.onStart();
        // Setup our view and list adapter. Ensure it scrolls to the bottom as data changes
        final ListView listView = getListView();
        // Tell our list adapter that we only want 50 messages at a time
        mChatListAdapter = new ChatListAdapter(mFirebaseRef.limit(50), this, R.layout.chat_message, mUsername);
        listView.setAdapter(mChatListAdapter);
        mChatListAdapter.registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                listView.setSelection(mChatListAdapter.getCount() - 1);
            }
        });

        // Finally, a little indication of connection status
        mConnectedListener = mFirebaseRef.getRoot().child(".info/connected").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                boolean connected = (Boolean) dataSnapshot.getValue();
                if (connected) {
                    Toast.makeText(MainActivity.this, "Connected to Firebase", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "Disconnected from Firebase", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {
                // No-op
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        mFirebaseRef.getRoot().child(".info/connected").removeEventListener(mConnectedListener);
        mChatListAdapter.cleanup();
    }

    private void setupUsername() {
        SharedPreferences prefs = getApplication().getSharedPreferences("ChatPrefs", 0);
        mUsername = prefs.getString("username", null);
        if (mUsername == null) {
            Random r = new Random();
            // Assign a random user name if we don't have one saved.
            mUsername = "JavaUser" + r.nextInt(100000);
            prefs.edit().putString("username", mUsername).commit();
        }
    }

    private void sendMessage() {
        EditText inputText = (EditText) findViewById(R.id.messageInput);
        String input = inputText.getText().toString();
        if (!input.equals("")) {
            // Create our 'model', a Chat object
            Chat chat = new Chat(input, mUsername,"Today : ");
            // Create a new, auto-generated child of that chat location, and save our chat data there
            mFirebaseRef.push().setValue(chat);
            inputText.setText("");

            Bundle b=new Bundle();
            b.putString("mUsername",mUsername);
            b.putString("mMessage",input);

            Intent intent = new Intent();
            intent.putExtras(b);
            intent.setAction("learning.firebase.app.learningfirebase.CUSTUM_INTENT");
            sendBroadcast(intent);

        }
    }

}


Chat.java


public class Chat {

    private String message;
    private String author;
    private String datetime;

    // Required default constructor for Firebase object mapping
    @SuppressWarnings("unused")

    Chat(String message, String author,String datetime) {
       this.message = message;
        this.author = author;
        this.datetime=datetime;
    }

    public String getMessage() {
        return message;
    }

    public String getAuthor() {
        return author;
    }

    public String getDatetime() {
        return datetime;
    }
}

ChatListAdapter.java

public class ChatListAdapter extends FirebaseListAdapter<Chat> {

    // The mUsername for this client. We use this to indicate which messages originated from this user
    private String mUsername;

    public ChatListAdapter(Query ref, Activity activity, int layout, String mUsername) {
        super(ref, Chat.class, layout, activity);
        this.mUsername = mUsername;
    }

    /**
     * Bind an instance of the <code>Chat</code> class to our view. This method is called by <code>FirebaseListAdapter</code>
     * when there is a data change, and we are given an instance of a View that corresponds to the layout that we passed
     * to the constructor, as well as a single <code>Chat</code> instance that represents the current data to bind.
     *
     * @param view A view instance corresponding to the layout we passed to the constructor.
     * @param chat An instance representing the current state of a chat message
     */
    @Override
    protected void populateView(View view, Chat chat) {
        // Map a Chat object to an entry in our listview
        String author = chat.getAuthor();
        TextView authorText = (TextView) view.findViewById(R.id.author);
        authorText.setText(author + ": ");
        // If the message was sent by this user, color it differently
        if (author != null && author.equals(mUsername)) {
            authorText.setTextColor(Color.RED);
        } else {
            authorText.setTextColor(Color.BLUE);
        }
        ((TextView) view.findViewById(R.id.message)).setText(chat.getMessage());
        ((TextView) view.findViewById(R.id.datetime)).setText(chat.getDatetime());
    }
}

我的Firebase截图

请帮我解决这个问题。我关注 firebase github 聊天项目。在我只添加一个值后,表示日期时间,我得到这个错误。

tl;dr:使 Chat class 静态并向其添加 parameterless/default 构造函数。

在单个文件中运行的最少代码 (Main.java):

public class Main {
    public static class Chat {
        private String message;
        private String author;
        private String datetime;

        // Required default constructor for Firebase object mapping
        public Chat() {}

        public Chat(String message, String author, String datetime) {
            this.message = message;
            this.author = author;
            this.datetime = datetime;
        }

        public String getMessage() { return message; }    
        public String getAuthor() { return author; }    
        public String getDatetime() { return datetime; }    
    }    

    public static void main(String[] args) throws Exception {
        Firebase ref = new Firebase("https://Whosebug.firebaseio.com/36675151/-KFaDuobfEA1FLslYZMM");
        ref.addListenerForSingleValueEvent(new ValueEventListener() {
            public void onDataChange(DataSnapshot dataSnapshot) {
                System.out.println(dataSnapshot.getValue(Chat.class));
            }

            public void onCancelled(FirebaseError error) {
            }
        });

        Thread.sleep(10000);
    }
}

JSON数据:

"-KFaDuobfEA1FLslYZMM": {
  "author": "user73181",
  "datetime": "today heyy",
  "message": "xjcjcj"
}

与您的代码不同的地方:

  • 我删除了所有与错误消息无关的内容。例如,这是一个 Java 程序,而不是 Android 程序。这个简单的改变消除了数以千计的潜在问题。但是既然你的问题依然存在,说明问题与Android无关。这种隔离问题的方法使查找原因变得容易得多。它通常被称为 minimal, complete/compilable verifiable example.
  • 我将所有内容都包含在一个文件中。这不仅使 copy/paste 更容易,还意味着文件之间的交互不能成为原因。在这种情况下,这确实意味着我必须 使 Chat class 静态 ,这可能是您出现问题的原因之一。
  • 我不得不 添加一个 parameterless/default 构造函数 ,这就是 Kato 在 [您之前的问题] 中指出的内容。 (Failed to bounce to type, Chat example error when adding another value,) 以及我告诉您要添加的内容。这可能是您问题的第二个原因。
  • 我将 JSON 添加为文本,而不是图像。这意味着您现在可以 copy/paste my JSON 查看您的问题是否源于此(顺便说一句,不是)。您可以通过单击 Firebase 仪表板中的“导出”按钮轻松获取 JSON。这样做让我不必再打字了。