java - 为什么我的 android Activity 偶尔会崩溃并显示 "No adapter attached; skipping layout"?

标签 java android android-fragments android-recyclerview

我正在开发一个 android 应用程序,它实际上是一个消息传递应用程序。

我正在使用 RecyclerView 来呈现特定对话的内容。

我坚持的是,我有一个 fragment ,它从用户那里获取输入来创建一个新的对话,我使用该信息来启动该对话的 Activity ,更新其布局,RecyclerView 的适配器等。

我在用户输入有效(非空等)时关闭 fragment ,在对话中发送测试消息并使用对话标识符启动对话 Activity 。

但是我得到了与 RecyclerView 相关的 NullPointerException,堆栈跟踪的标题是:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$LayoutManager.onAddFocusables(android.support.v7.widget.RecyclerView, java.util.ArrayList, int, int)' on a null object reference

在此之上,我还听到一句话 No adapter attached;跳过布局

我在 stackoverflow 上看到的答案是,您应该先启动一个 Adapter/LayoutManager,然后将其附加到 RecyclerView,但我已经在这样做了。

我在这里写我的代码 fragment 。

Interface method that gets invoked when user input is valid.

public void onCreateConversation(DialogFragment dialog, String conversationName) {

    dialog.dismiss();

    Conversation newConversation = client.newConversation(Arrays.asList(userList);
    String identifier = newConversation.getId().toString();

    // prepare initiation message
    String initialMessageText = "starting conversation";
    MessagePart initialMessagePart = client.newMessagePart("text/initiation", initialMessageText.getBytes());
    Message initialMessage = client.newMessage(Arrays.asList(initialMessagePart));

    // send initiation message
    newConversation.send(initialMessage);

    startConversationActivity(identifier);
}

Start an activity for the conversation

public void startConversationActivity(String identifier) {

    Intent intent = new Intent(this, ChatConversationActivity.class);
    intent.putExtra("IDENTIFIER", identifier);

    startActivity(intent);
}

The onCreate method of ChatConversationActivity

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.loading_conversation);

    Intent intent = getIntent();
    conversationIdentifier = intent.getStringExtra("IDENTIFIER");

    // argument 'client' is reference to the connection
    conversationViewControl = new ConversationViewController(this, client, conversationIdentifier);
}

In the constructor of ConversationViewController

public ConversationViewController(ChatConversationActivity activity, Client client, String identifier) {
    activity.setContentView(R.layout.activity_conversation);

    // messages recycler view
    messageRecyclerView = (RecyclerView) activity.findViewById(R.id.messageRecyclerView);

    // layout manager for recycler view
    recyclerViewLayoutManager = new LinearLayoutManager(activity);

    // message adapter
    MessageAdapter = null;

    // private conversation object in ConversationViewController
    activeConversation = getConversation(identifier);

    // this will render the layout for conversation
    drawConversationView(activeConversation);
}

'getConversation' asks the service for conversation with an identifier

private Conversation getConversation(String identifier) {

    if(activeConversation == null) {
        Query query = Query.builder(Conversation.class)
                .predicate(new Predicate(Conversation.Property.ID, Predicate.Operator.EQUAL_TO, identifier))
                .build();

        List<Conversation> results = client.executeQuery(query, Query.ResultType.OBJECTS);
        if(results != null && results.size() > 0) {

            // loading first object as identifiers are unique for all conversations
            return results.get(0);
        }

    }

    return activeConversation;
}

'drawConversationView' will update the view for conversation

private void drawConversation(Conversation conversation) {

    // Only proceed if there is a valid conversation
    if(conversation != null) {
        Log.d("create conversation", "activeConversation is not null");

        // recycler view layout manager
        recyclerViewLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        messageRecyclerView.setLayoutManager(recyclerViewLayoutManager);

        // messages for the conversation
        List<Message> messages = client.getMessages(conversation);

        // recycler view adapter, 'activity' is also private object
        messageAdapter = new MessageAdapter(messages, activity);
        messageRecyclerView.setAdapter(messageAdapter);
    } else {
        Log.d("create conversation", "activeConversation is still null");
    }
}

这东西随机崩溃,有时会创建对话,我可以看到它的 View ,有时却看不到。

我是 Java 和 Android 领域的新手,你能帮我跟踪一下吗?

最佳答案

我可以在您的代码中看到两个不合理的地方。

Attach the LayoutManager as soon as you collect a reference to RecyclerView

您可以尝试在 ConversationViewController 本身中将 LayoutManager 附加到 RecyclerView,然后再尝试收集对话数据。

    ...
    // messages recycler view
    messageRecyclerView = (RecyclerView) mca.findViewById(R.id.messageRecyclerView);

    // layout manager for recycler view
    recyclerViewLayoutManager = new LinearLayoutManager(mca);
    recyclerViewLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

    // set this right here
    messageRecyclerView.setLayoutManager(recyclerViewLayoutManager);
    ...

这可能会使您免于崩溃。

Implement callbacks to make sure you render only when you have the data

ConversationViewController 中,您依次调用了 getConversationdrawConversation 方法,但是您首先收集了一些数据并使用第二种方法。

您可以尝试实现一个接口(interface),并使用它从方法 getConversation 中调用 drawConversation,一旦您拥有对话数据,而不是同步调用它们。

希望本文对您有所帮助。

关于java - 为什么我的 android Activity 偶尔会崩溃并显示 "No adapter attached; skipping layout"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31276294/

相关文章:

java - 下面的线程代码中的synchronized是如何工作的,代码流程是怎样的?

安卓。报警管理器。重复警报不触发,一段时间后,一次触发所有警报

android - 在 ScrollView 中没有滚动

Android Theme AppCompat 如何设置菜单项选择器的样式

android - 我怎么知道再访问 Fragment ChildFragmentManager 是否安全?

android - 通过抽屉导航将先前的 fragment 替换为新 fragment 时, Volley 在新 fragment 中显示先前的 fragment 响应

java - png 图像文件到视频(无损)

java - jBPM 和 JPA 事务管理器 : no local transaction to join

java - "MAIN"和 "LAUNCHER"对于启动器 Activity 是多余的

android - 动画 fragment 导致其他 View 变为 "jump"