2017-09-02 26 views
0

我搜查了FirebaseRecyclerAdapter和相关类的文档,但无法找到我想要的方法(无需自己重新构建库)。用于消息传递应用程序的FirebaseRecyclerAdapter

我正在开发一个内置消息传递的应用程序(包括组和直接消息传递其他用户)。

群聊可以工作,因为它会从群聊节点下的数据库引用中提取每条消息。

直接消息正在变得棘手。我想跳过参考中不包含当前用户的模型ID的节点以及他们试图发送消息的用户(以便他们不能看到其他人的消息)。

在下面的代码中,我试图返回null如果viewType = 10,因为我不希望聊天气泡显示......正如您所期望的,我从RecyclerViewAdapter类中得到一个空指针异常。

我知道为什么我得到错误。我故意将null传递给它,试图跳过(或迭代当前项目),而不在任何位置显示聊天气泡。

这里是我的火力结构(出口JSON):Database Structure

这里是供参考堆栈跟踪:

FATAL EXCEPTION: main 
                     Process: com.aztechdev.squad, PID: 21249 
                   java.lang.NullPointerException: Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null object reference 
                    at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6368) 
                    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5555) 
                    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440) 
                    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436) 
                    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224) 
                    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551) 
                    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511) 
                    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:570) 
                    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3583) 
                    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3312) 
                    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3844) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741) 
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585) 
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at com.mxn.soul.flowingdrawer_core.FlowingDrawer.onLayout(FlowingDrawer.java:138) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1795) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1197) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:131) 
                    at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42) 
                    at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1391) 
                    at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:870) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1193) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741) 
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585) 
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 
09-02 10:47:22.899 21249-21249/com.aztechdev.squad E/AndroidRuntime:  at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741) 
                    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585) 
                    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 
                    at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 
                    at com.android.internal.policy.DecorView.onLayout(DecorView.java:726) 
                    at android.view.View.layout(View.java:17637) 
                    at android.view.ViewGroup.layout(ViewGroup.java:5575) 
                    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2346) 
                    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2068) 
                    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254) 
                    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337) 
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874) 
                    at android.view.Choreographer.doCallbacks(Choreographer.java:686) 
                    at android.view.Choreographer.doFrame(Choreographer.java:621) 
                    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860) 
                    at android.os.Handler.handleCallback(Handler.java:751) 
                    at android.os.Handler.dispatchMessage(Handler.java:95) 
                    at android.os.Looper.loop(Looper.java:154) 
                    at android.app.ActivityThread.main(ActivityThread.java:6119) 
                    at java.lang.reflect.Method.invoke(Native Method) 
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

这里是我的FirebaseRecyclerAdapter:

package com.aztechdev.squad.adapter; 

import android.content.Context; 
import android.support.v7.widget.RecyclerView; 
import android.text.format.DateUtils; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 
import android.widget.TextView; 
import com.aztechdev.squad.helpers.common; 
import com.aztechdev.squad.model.DirectChatModel; 
import com.firebase.ui.database.FirebaseRecyclerAdapter; 
import com.google.firebase.database.DatabaseReference; 
import hani.momanii.supernova_emoji_library.Helper.EmojiconTextView; 

import com.aztechdev.squad.R; 


public class DirectFirebaseAdapter extends FirebaseRecyclerAdapter<DirectChatModel,DirectFirebaseAdapter.MyChatViewHolder> { 

private static final int RIGHT_MSG = 0; 
private static final int LEFT_MSG = 1; 
private static final int RIGHT_MSG_IMG = 2; 
private static final int LEFT_MSG_IMG = 3; 

public static final String TAG = "DirectFirebaseAdapter"; 
private ClickListenerChatFirebase mClickListenerChatFirebase; 

private String mUID; 
private Context mContext; 

public DirectFirebaseAdapter(Context context, DatabaseReference ref, String mUID, ClickListenerChatFirebase mClickListenerChatFirebase) { 
    super(DirectChatModel.class, R.layout.item_message_left, DirectFirebaseAdapter.MyChatViewHolder.class, ref); 
    this.mUID = mUID; 
    this.mClickListenerChatFirebase = mClickListenerChatFirebase; 
    this.mContext = context; 

} 


@Override 
public MyChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view; 
    if (viewType == RIGHT_MSG){ 
     view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_right,parent,false); 
     return new MyChatViewHolder(view); 
    }else if (viewType == LEFT_MSG){ 
     view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_left,parent,false); 
     return new MyChatViewHolder(view); 
    }else if (viewType == RIGHT_MSG_IMG){ 
     view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_right_img,parent,false); 
     return new MyChatViewHolder(view); 
    } else if (viewType == 10) { 
     return null; 
    } else { 
     view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_left_img,parent,false); 
     return new MyChatViewHolder(view); 
    } 
} 


@Override 
public int getItemViewType(int position) { 

    DirectChatModel model = getItem(position); 

    Log.d(TAG, "getItemCount: " + getItemCount()); 
    Log.d(TAG, "From UID: " + model.getFrom().getId()); 
    Log.d(TAG, "To UID: " + model.getTo().getId()); 


    **if (!model.getFrom().getId().equals(mUID) && !model.getTo().getId().equals(mUID)) { 
     Log.d(TAG, "getItemViewType: UID not found"); 
     return 10; 
    }** 


    if (model.getMapModel() != null){ 
     if (model.getFrom().getId().equals(mUID)){ 
      return RIGHT_MSG_IMG; 
     }else{ 
      return LEFT_MSG_IMG; 
     } 
    }else if (model.getFile() != null){ 
     if (model.getFile().getType().equals("img") && model.getFrom().getId().equals(mUID)){ 
      return RIGHT_MSG_IMG; 
     }else{ 
      return LEFT_MSG_IMG; 
     } 
    }else if (model.getFrom().getId().equals(mUID)){ 
     return RIGHT_MSG; 
    }else { 
     return LEFT_MSG; 
    } 
} 

@Override 
protected void populateViewHolder(MyChatViewHolder viewHolder, DirectChatModel model, int position) { 

    if (model.getTo().getId().equals(mUID)) { 
     viewHolder.setIvUser(model.getTo().getPhoto_profile()); 
     viewHolder.setTvTimestamp(model.getTimeStamp(), model.getTo().getName()); 

    } else { 
     viewHolder.setIvUser(model.getFrom().getPhoto_profile()); 
     viewHolder.setTvTimestamp(model.getTimeStamp(), model.getFrom().getName()); 

    } 

    viewHolder.setTxtMessage(model.getMessage()); 
    viewHolder.tvIsLocation(View.GONE); 
    if (model.getFile() != null){ 
     viewHolder.tvIsLocation(View.GONE); 
     viewHolder.setIvChatPhoto(model.getFile().getUrl_file()); 
    }else if(model.getMapModel() != null){ 
     viewHolder.setIvChatPhoto(common.local(model.getMapModel().getLatitude(),model.getMapModel().getLongitude())); 
     viewHolder.tvIsLocation(View.VISIBLE); 
    } 
} 


public class MyChatViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 

    TextView tvTimestamp,tvLocation; 
    EmojiconTextView txtMessage; 
    ImageView ivUser,ivChatPhoto; 

    public MyChatViewHolder(View itemView) { 
     super(itemView); 
     tvTimestamp = (TextView)itemView.findViewById(R.id.timestamp); 
     txtMessage = (EmojiconTextView)itemView.findViewById(R.id.txtMessage); 
     tvLocation = (TextView)itemView.findViewById(R.id.tvLocation); 
     ivChatPhoto = (ImageView)itemView.findViewById(R.id.img_chat); 
     ivUser = (ImageView)itemView.findViewById(R.id.ivUserChat); 
    } 

    @Override 
    public void onClick(View view) { 
     int position = getAdapterPosition(); 
     DirectChatModel model = getItem(position); 
     if (model.getMapModel() != null){ 
      mClickListenerChatFirebase.clickImageMapChat(view,position,model.getMapModel().getLatitude(),model.getMapModel().getLongitude()); 
     }else{ 
      // mClickListenerChatFirebase.clickImageChat(view,position,model.getUserModel().getName(),model.getUserModel().getPhoto_profile(),model.getFile().getUrl_file()); 
     } 
    } 

    public void setTxtMessage(String message){ 
     if (txtMessage == null)return; 
     txtMessage.setText(message); 
    } 

    public void setIvUser(String urlPhotoUser){ 
     if (ivUser == null)return; 
     CircleTransform circleTransform = new CircleTransform(); 
     GlideApp.with(ivUser.getContext()).load(urlPhotoUser).centerCrop().transform(circleTransform).override(160,160).into(ivUser); 

    } 

    public void setTvTimestamp(String timestamp, String sender){ 
     if (tvTimestamp == null)return; 
     tvTimestamp.setText(sender + " - " + convertTimestamp(timestamp)); 
    } 

    public void setIvChatPhoto(String url){ 
     if (ivChatPhoto == null)return; 

     GlideApp.with(ivChatPhoto.getContext()).load(url) 
       .override(200, 200) 
       .fitCenter() 
       .into(ivChatPhoto); 
     ivChatPhoto.setOnClickListener(this); 
    } 

    public void tvIsLocation(int visible){ 
     if (tvLocation == null)return; 
     tvLocation.setVisibility(visible); 
    } 

} 

private CharSequence convertTimestamp(String millis){ 
    return DateUtils.getRelativeTimeSpanString(Long.parseLong(millis), System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS); 
} 

} 

回答

0

你有三个选项:

  1. 改变你的数据结构,所以你不需要跳过行。这是长期绩效的最佳选择,但如果您只是想通过POC,可能不是您的偏好。

  2. 请勿使用FirebaseUI。使用基本Firebase库自行运行查询。然后在客户端上处理结果以删除/省略不需要的行。您必须将实际的行数返回给RecyclerView,而不需要那些您想省略的行,并且只有您想要的行有一个干净的数组是最简单的方法。

  3. 快速入侵:不是返回null,而是返回0高度视图!这是一个非常丑陋的黑客,但它确实有效。

相关问题