如何独立地从属于 android/java 中同一组的嵌套 JSON objects 中检索数据? (正文中还有 clarity/details)

How do I retrieve data independently from nested JSON objects that are part of the same group in android/java? ( more clarity/details in body)

我有一个很常见的情况,但我一直在尝试弄清楚如何在相同的 json 响应中从某些 json objects 检索数据,但返回不同大小的项目。 为了减少混淆,这是我的 json 回复:

{
    "totalResults": 5,
    "meetings": [
        {
            "id": "754e6670-2376-4eb2-b5f6-ea63ca7c2669",
            "dateStart": "2019-11-28T15:25:36.000Z",
            "dateEnd": "2019-11-28T23:00:36.000Z",
            "visitors": [
                {
                    "visitId": "34608af6-bbe4-439c-b472-500790385f60",
                    "firstName": "Lord",
                    "lastName": "Wilkins",
                    "email": "  lwilkins@df.dj",
                },
                {
                    "visitId": "fe61e1f0-34f1-4701-b806-45395980acfb",
                    "firstName": "cg",
                    "lastName": "cg",
                    "email": "cg@gg.hg",
                },
                {
                    "visitId": "226eed33-b2ca-4406-b085-8534c2f87c69",
                    "firstName": "ar",
                    "lastName": "fg",
                    "email": "ar@gg.hh",
                }
            ]
        },
        {
            "id": "cf6934c1-3800-4b79-9d0f-570934097d26",
            "dateStart": "2019-11-30T00:00:06.000Z",
            "dateEnd": "2019-11-30T02:00:06.000Z",
            "visitors": [
                {
                    "visitId": "03a01b91-f307-4a04-ae7a-71a5e3e183c5",
                    "firstName": "ar",
                    "lastName": "fg",
                    "email": "ar@gg.hh",
                }
            ]
        },
        {
            "id": "a46130c3-5b80-419e-8c57-e17428d4b735",
            "dateStart": "2019-11-28T13:00:09.000Z",
            "dateEnd": "2019-11-29T02:45:09.000Z",
            "visitors": [
                {
                    "visitId": "5068a774-1cf3-45e2-af65-b98ab4dfbff2",
                    "firstName": "dot",
                    "lastName": "mn",
                    "email": "dtmn@gg.gh",
                }
            ]
        }
    ]
}

如果有人感兴趣,这是我的模型 class:https://pastebin.com/fUmiBiQP

现在,我正在尝试检索开始日期和结束日期并将其放在名字和姓氏以及电子邮件的顶部,如下所示:

" Nov 28, 2:00pm - 6:00 pm 
  lord wilkins
  lwilkins@df.dj

  Nov 28, 2:00pm - 6:00 pm 
  cg cg
  cg@gg.hg"

请注意我如何重复适用于组合在一起的条目的相同日期,我想实现这一点,但目前我只能检索名字和姓氏以及电子邮件,但不是基于我如何安排我的代码的日期。每次我尝试修改代码以包括会议开始和结束日期时,它都会因大小导致索引越界异常或适配器中发生空指针 exception.The 问题而崩溃。 这是我的适配器代码供参考:

public class UpcomingGuestListAdapter extends RecyclerView.Adapter<BaseViewHolder>  {

    private Context context;
    private UpcomingGuestListAdapter.Callback mCallback;
    private List<UpcomingGuestsList.Visitor> mUpcomingGuestListResponseList;
    private List<UpcomingGuestsList.Meeting> mUpcomingGuestListResponseMeetingList;

    public class MyViewHolder extends BaseViewHolder {
        public TextView name, email, arrivalDate;


        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            Timber.d("viewholder butterknife bind");
            name = itemView.findViewById(R.id.upcoming_guest_name);
            email = itemView.findViewById(R.id.upcoming_guest_email);
            arrivalDate = itemView.findViewById(R.id.arrival_date);
            ButterKnife.bind(this, itemView);
        }

        @Override
        protected void clear() {

        }
        public void onBind(int position) {
            super.onBind(position);
            final UpcomingGuestsList.Visitor guest = mUpcomingGuestListResponseList.get(position);
            final UpcomingGuestsList.Meeting meeting = mUpcomingGuestListResponseMeetingList.get(position);

            String guestWholeName = guest.firstName + " "+ guest.lastName;
            if( guest.getFirstName() != null && guest.getLastName() != null) {
                name.setText(guestWholeName);
            }



            if (guest.getEmail() != null) {
                email.setText(guest.getEmail());
            } else {
                email.setText("");
            }

            String meetingDate = meeting.dateStart + "-"+ meeting.dateEnd;
            if( meeting.getDateStart() != null && meeting.getDateEnd() != null) {
                arrivalDate.setText(meetingDate);
            }
            itemView.setOnClickListener(v -> {
                if(mCallback != null) {
                    mCallback.onItemClick( guest.getFirstName(), guest.getLastName(), guest.getEmail());
                }
            });

        }

    }

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_upcoming_guest, parent, false);

        return new UpcomingGuestListAdapter.MyViewHolder(itemView);
    }

    public interface Callback {
        void onItemClick(String guestFirstName, String guestLastName,String guestEmail);

    }

    @Override
    public long getItemId(int position) {
        Timber.d("item id for eventlist adapter : %s",position);
        return position;
    }

    public void addItems(@NonNull List<UpcomingGuestsList.Visitor> repoList) {

        mUpcomingGuestListResponseList.addAll(repoList);
         notifyDataSetChanged();
    }

    public void addMeetingItems(@NonNull List<UpcomingGuestsList.Meeting> meetingList) {
        mUpcomingGuestListResponseMeetingList.addAll(meetingList);
        notifyDataSetChanged();
    }
    @Override
    public void onBindViewHolder(BaseViewHolder holder, final int position) {
        holder.onBind(position);

    }

    public UpcomingGuestListAdapter(Context context, List<UpcomingGuestsList.Visitor> visitorGuestList, List<UpcomingGuestsList.Meeting> meetingList) {
        Timber.d("SearchGuestListAdapter constructor");
        this.context = context;
        this.mUpcomingGuestListResponseList = visitorGuestList;
        this.mUpcomingGuestListResponseMeetingList = meetingList;


    }

    @Override
    public int getItemCount() {

        return (mUpcomingGuestListResponseList  != null)?mUpcomingGuestListResponseList.size():0;
    }

    public void setCallback(UpcomingGuestListAdapter.Callback callback) {
        mCallback = callback;
    }

}

这是 activity 中的代码,它从中获取数据:

   @Override
    public void updateUpcomingGuestList(List<UpcomingGuestsList.Visitor> guestList,List<UpcomingGuestsList.Meeting> meetingList) {

        mUpcomingGuestAdapter.addItems(guestList);
        mUpcomingGuestAdapter.addMeetingItems(meetingList);
        mUpcomingGuestAdapter.notifyDataSetChanged();
    }

在同一个 activity 中,这就是我在创建时设置适配器的方式:

   guestList = new ArrayList<>();
        mUpcomingGuestAdapter = new UpcomingGuestListAdapter(this, guestList, meetingList);
        mUpcomingGuestAdapter.setCallback(this);
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.setAdapter(mUpcomingGuestAdapter);
        mPresenter.onViewPrepared();

以及我在其中检索 json 数据的 viewprepared 代码:

 @Override
    public void onViewPrepared() {
        getCompositeDisposable().add(getDataManager()
                .getUpcomingGuestListApiCall(AppPreferencesHelper.getInstance().getCurrentUserId())
                .subscribeOn(getSchedulerProvider().io())
                .observeOn(getSchedulerProvider().ui())
                .subscribe(response -> {
                    int sizercount = 0;
                    for (int i = 0; i <response.totalResults; i++) {
                            Objects.requireNonNull(getMvpView()).updateUpcomingGuestList(response.meetings.get(i).getVisitors(),response.getMeetings());

                            sizercount++;
                    }

                    totalGuests = sizercount;

                    Timber.d("total results value is : from upcomingguests %s",response.totalResults);
                    getDataManager().getUpcomingGuestsList();
                    AppPreferencesHelper.getInstance().setTotalUpcomingGuestCount(sizercount);

                }, throwable -> {
                    if (!isViewAttached()) {
                        return;
                    }

                    // handle the error here

                    if (throwable instanceof ANError) {
                        ANError anError = (ANError) throwable;
                        Timber.d("it is ERROR in displaylocation in Registervisitorpresenter:%s", anError.getErrorDetail());

                        handleApiError(anError);
                    }
                }));
    }

正如你从上面看到的,我尝试在这里一起检索访问者列表和会议列表:Objects.requireNonNull(getMvpView()).updateUpcomingGuestList(response.meetings.get(i ).getVisitors(),response.getMeetings()); ,但不确定这样做是否正确,因为访客列表和会议列表根据数据有不同的 positions/size,这可能导致 crash.Is 有办法解决这个问题并更新我的代码,以便我可以将正确的日期分配给正确的访问者,以便我可以获得上面列出的输出?任何帮助表示赞赏。

谢谢!如果需要,很乐意分享更多信息。

与其尝试使用来自您的 API 的响应(这会导致问题),您可以声明一个更友好的模型 class 并在您的 API 响应以创建新模型列表 class。

声明一个新模型 UpcomingGuest,它在其构造函数中接受一个 Visitor 对象和一个 Meeting。

public class UpcomingGuest {


    private String visitId;

    private String firstName;

    private String lastName;

    private String email;

    private Object phone;

    private String status;

    private String meetingId;

    private String meetingDateStart;

    private String meetingDateEnd;

    public UpcomingGuest(UpcomingGuestsList.Visitor visitor, UpcomingGuestsList.Meeting meeting){

        this.visitId = visitor.getVisitId();
        this.firstName = visitor.getFirstName();
        this.lastName = visitor.getLastName();
        this.email = visitor.getEmail();
        this.phone = visitor.getPhone();
        this.status = visitor.getStatus();
        this.meetingId = meeting.getId();
        this.meetingDateStart = meeting.getDateStart();
        this.meetingDateEnd = meeting.getDateEnd();

    }

    public String getVisitId() {
        return visitId;
    }

    public void setVisitId(String visitId) {
        this.visitId = visitId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Object getPhone() {
        return phone;
    }

    public void setPhone(Object phone) {
        this.phone = phone;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getMeetingId() {
        return meetingId;
    }

    public void setMeetingId(String meetingId) {
        this.meetingId = meetingId;
    }

    public String getMeetingDateStart() {
        return meetingDateStart;
    }

    public void setMeetingDateStart(String meetingDateStart) {
        this.meetingDateStart = meetingDateStart;
    }

    public String getMeetingDateEnd() {
        return meetingDateEnd;
    }

    public void setMeetingDateEnd(String meetingDateEnd) {
        this.meetingDateEnd = meetingDateEnd;
    }


}

然后根据您的响应构建一个 UpcomingGuest 列表,该列表将在您的 RecyclerView 的适配器中使用。

.subscribe(response -> {
                    int sizercount = 0;
                    for (UpcomingGuestsList.Meeting meeting: response.meetings) {
                        for(UpcomingGuestsList.Visitor visitor: meeting.visitors){
                            upcomingGuests.add(new UpcomingGuest(visitor,meeting));
                        }
                    }

                    // send upcomingGuests results to view


                }

然后在您的 RecyclerView 适配器中使用一个 UpcomingGuest 列表,而不是您正在使用的两个列表。

private List<UpcomingGuest> mUpcomingGuestList;

编辑

对于您的排序问题,您可以在循环之前对您的回复进行排序,如下所示:

.subscribe(response -> {
        ArrayList<UpcomingGuest> upcomingGuests = new ArrayList<>();

        //sort meetings by date
        List<UpcomingGuestsList.Meeting> meetings = response.meetings;
        Collections.sort(meetings, new Comparator<UpcomingGuestsList.Meeting>() {
            @Override
            public int compare(UpcomingGuestsList.Meeting meeting, UpcomingGuestsList.Meeting t1) {
                return meeting.getDateStart().compareTo(t1.getDateStart());
            }
        });

        for (UpcomingGuestsList.Meeting meeting: meetings) {
            //sort visitors by last name
            List<UpcomingGuestsList.Visitor> visitors = meeting.visitors;
            Collections.sort(visitors, new Comparator<UpcomingGuestsList.Visitor>() {
                @Override
                public int compare(UpcomingGuestsList.Visitor visitor, UpcomingGuestsList.Visitor t1) {
                    return visitor.getLastName().compareTo(t1.getLastName());
                }
            });

            for(UpcomingGuestsList.Visitor visitor: visitors){

                upcomingGuests.add(new UpcomingGuest(visitor,meeting));
            }
        }

        // send upcomingGuests results to view


}