java - 如何独立于嵌套的 JSON 对象检索数据,这些对象属于 android/java 中的同一组? ( body 更清晰/细节)

标签 java android android-activity android-adapter android-json

我有一个很常见的场景,但我一直在尝试弄清楚如何从同一 json 响应中的某些 json 对象检索数据,但返回不同大小的项目。 为了减少混淆,这是我的 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",
                }
            ]
        }
    ]
}

如果有人感兴趣,这是我的模型类: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"

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

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);
                    }
                }));
    }

正如您从上面看到的,我尝试在这里一起检索访问者列表和 session 列表:Objects.requireNonNull(getMvpView()).updateUpcomingGuestList(response.meetings.get(i).getVisitors(), response.getMeetings()); ,但不确定这样做是否正确,因为访客列表和 session 列表根据数据具有不同的位置/大小,这可能导致崩溃。有没有办法解决这个问题并更新我的代码,所以我可以将正确的日期分配给正确的访问者,以便我可以实现上面列出的输出吗?任何帮助表示赞赏。

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

最佳答案

与其尝试使用来自您的 API 的响应(这会导致问题),您可以声明一个更友好的模型类,并对您的 API 响应执行一些操作以创建新模型类的列表.

声明一个新模型 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


}

关于java - 如何独立于嵌套的 JSON 对象检索数据,这些对象属于 android/java 中的同一组? ( body 更清晰/细节),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59079651/

相关文章:

硬编码参数时的 Java 异常处理

Scala 中的 JavaFX 2 和 setCellValueFactory()?

java - Android Tabbed Activity 复制标签

android - 扩展 Activity 的标题未出现自定义样式

android - 如何显示不同 Activity 的警报

java - 链表堆栈丢失最后一个压入堆栈的项目

java - 如何解决jsp到servlet的空间问题?

android - 如何在Android中制作一个不会自行折叠的通知?

java - Android 和 Java key 生成返回不同的结果

java - 有没有办法准确检测 Android 中的 Activity 何时被销毁?