通过LiveData观察dataList时,通过服务RecyclerView故障调用API的问题

问题描述

我必须实时显示数据。所以我创建了一个服务并添加了一个计时器。我每隔1分钟点击一次Rest API,并将数据存储在Room-Bb中。

问题:每隔一分钟,当服务被调用时,我的适配器被重置,而我的recyclerView每隔一分钟又一次闪烁,即使滚动列表我也到达列表的顶部。

在我作为片段基础的活动中,我将MySimpleService称为。在服务中,我每1分钟使用计时器调用一次我的API,以检查是否有任何新预订。而且每当调用我的API时,由于适配器中setBookingData方法中的notifydatasetchanged(),我的列表就会更新,并且Recyclerview Adapter会重置。因此,我的recyclerView每隔一分钟就会继续闪烁。

这是我的代码

MySimpleService

 public class MySimpleService extends Service {
        private static final String TAG = "MyTag";
        private Timer mTimer;
        private Handler mHandler = new Handler();
        private static final int TIMER_INTERVAL = 10000; // 1 Minute
        private static final int TIMER_DELAY = 0;
        private MyDatabase appDatabase;
    
        @Override
        public void onCreate() {
            super.onCreate();
            appDatabase = MyDatabase.getInstance(getApplicationContext());
            Log.d(TAG,"MySimpleService onCreate: ");
            if (mTimer != null)
                mTimer = null;
            // Create new Timer
            mTimer = new Timer();
            // Required to Schedule DisplayToastTimerTask for repeated execution with an interval of `1 min`
            mTimer.scheduleAtFixedRate(new DisplayToastTimerTask(),TIMER_DELAY,TIMER_INTERVAL);
        }
    
        @Override
        public int onStartCommand(Intent intent,int flags,int startId) {
            Log.d(TAG,"MySimpleService onStartCommand: ");
            return Service.START_STICKY;
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e(TAG,"My Service onDestroy: ");
            // Cancel timer
            mTimer.cancel();
        }
    
    
        private class DisplayToastTimerTask extends TimerTask {
            @Override
            public void run() {
                mHandler.post(() -> {
                    if (Utils.getConnectivityStatus(getApplicationContext()) == 0) {
                        Utils.showOkAlert(getApplicationContext(),getString(R.string.info),"Please check your internet connection",false);
                    } else {
                        new Thread(() -> callApbookingList()).start();
                        new Thread(() -> callApiAssignList()).start();
                        new Thread(() -> callApiBookingActivitiesList()).start();
                    }
                });
            }
        }
    
        private  void callApbookingList() {
            RetrofitApiInterface apiInterface = RetrofitClient.getClient().create(RetrofitApiInterface.class);
            Call<BookingDataResponse> call = apiInterface.getAllData(new PostContData(PreferenceData.getLong(getApplicationContext(),"cont_id")));
            call.enqueue(new Callback<BookingDataResponse>() {
                @Override
                public void onResponse(Call<BookingDataResponse> call,Response<BookingDataResponse> response) {
                    if (response.isSuccessful()) {
                        BookingDataResponse body = response.body();
                        appDatabase.myDao().deleteBookingList();
                        if (body.getStatus() == 0) {
                            Log.d(TAG,"onResponse: " + body.getMessage());
                                new Thread(() -> {
                                    try {
                                        appDatabase.myDao().insertBooking(body.getBookingList());
                                    } catch (Exception e) {
                                    }
                                }).start();
                        }
                    }
                }
    
                @Override
                public void onFailure(Call<BookingDataResponse> call,Throwable t) {
                    Log.e(TAG,"onFailure: " + t);
                }
            });
        }

我的片段

public class BookingAssignFragment extends Fragment {
    private BookingViewModel bookingViewModel;
    private BookingListAdepter bookingListAdepter;


    public BookingAssignFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_booking_assign,container,false);
        bookingListAdepter = new BookingListAdepter(getActivity());
        RecyclerView recyclerView = view.findViewById(R.id.rev_booking_list);
        TextView errorMessasge = view.findViewById(R.id.error_message);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAdapter(bookingListAdepter);
        bookingViewModel = new ViewModelProvider(getActivity()).get(BookingViewModel.class);
        bookingViewModel.getBooking().observe(getActivity(),bookingLists -> {
            if (bookingLists.isEmpty()) {
                if (errorMessasge.getVisibility() == View.GONE)
                    errorMessasge.setVisibility(View.VISIBLE);
            } else {
                if (errorMessasge.getVisibility() == View.VISIBLE)
                    errorMessasge.setVisibility(View.GONE);
              //  bookingListAdepter.setBookingData(bookingLists);
            }
            bookingListAdepter.setBookingData(bookingLists);
        });
        return view;
    }

}

我的适配器

   public class BookingListAdepter extends RecyclerView.Adapter<BookingListAdepter.BookingViewHolder> {
    private List<BookingList> bookingLists;
    private  LayoutInflater mInflater;
    private Context mContext;

    public BookingListAdepter(Context context) {
        mInflater = LayoutInflater.from(context);
        mContext =context;
    }

    @NonNull
    @Override
    public BookingViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
        View  view = mInflater.inflate(R.layout.item_view_booking_list,parent,false);
        return new BookingViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull BookingViewHolder holder,int position) {
        BookingList li = bookingLists.get(position);
        if(li.getPlanType().equalsIgnoreCase("Both Way")){
            if (holder.numberOfDay.getVisibility()==View.GONE) {
                holder.numberOfDay.setVisibility(View.VISIBLE);
                holder.numberOfDay.setText(String.valueOf(li.getBookingDays()));
            }
        }else {
            if (holder.numberOfDay.getVisibility()==View.VISIBLE)
            holder.numberOfDay.setVisibility(View.GONE);
           }
        if (li.getPlanType().equals(li.getTerrifType())){
            if (holder.palanTyupe.getVisibility()==View.VISIBLE)
            holder.palanTyupe.setVisibility(View.GONE);
        }else { if (holder.palanTyupe.getVisibility()==View.GONE)
            holder.palanTyupe.setVisibility(View.VISIBLE);}
        holder.packageName.setText(li.getPlanType());
        holder.cabCategory.setText(li.getCabCategory());
        holder.dateTime.setText(li.getDatetime());
        holder.formLocation.setText(li.getFromLocation());
        holder.toLocation.setText(li.getToLocation());
        holder.amount.setText(String.valueOf(li.getTotalAmount()));
        holder.paidWalletAmount.setText(String.valueOf(li.getPaidWalletAmount()));
        holder.assignBooking.setOnClickListener(v -> {
            if (Utils.getConnectivityStatus(mContext) == 0) {
                Utils.showOkAlert(mContext,mContext.getString(R.string.info),false);
            }else {
                BookingAssignDialogFragment updateDriver = BookingAssignDialogFragment.newInstance(li.getBookingId(),PreferenceData.getLong(mContext,"cont_id"),"");
                updateDriver.show((Activity) mContext);
            }
        });
    }

    @Override
    public int getItemCount() {
        if (bookingLists!=null)
            return bookingLists.size();
        else return 0;
    }
    public void setBookingData(List<BookingList> bookingData) {
        bookingLists = bookingData;
        Log.d("UpdatedBooking",String.valueOf(bookingLists.size()));
        notifyDataSetChanged();
    }
    class BookingViewHolder extends RecyclerView.ViewHolder{
     TextView packageName,palanTyupe,cabCategory,amount,formLocation,toLocation,dateTime,numberOfDay,paidWalletAmount;
     ImageView assignBooking,acceptBooking;
        public BookingViewHolder(@NonNull View itemView) {
            super(itemView);
            packageName = itemView.findViewById(R.id.package_name);
            palanTyupe = itemView.findViewById(R.id.plan_type);
            cabCategory = itemView.findViewById(R.id.cab_category);
            amount = itemView.findViewById(R.id.amount);
            formLocation = itemView.findViewById(R.id.from_location);
            toLocation = itemView.findViewById(R.id.to_location);
            dateTime = itemView.findViewById(R.id.date_and_time);
            numberOfDay = itemView.findViewById(R.id.no_of_day);
            assignBooking = itemView.findViewById(R.id.assign_booking);
            paidWalletAmount = itemView.findViewById(R.id.paid_wallet_amount);
            acceptBooking =itemView.findViewById(R.id.accept_booking);
        }
    }
}

我的ViewModel

public class BookingActivitiesListViewModel extends AndroidViewModel {


    private BookingActivitiesListRepository bookingActivitiesListRepository;
    private LiveData<List<BookingActivitiesList>> mLiveData;

    public BookingActivitiesListViewModel(@NonNull Application application) {
        super(application);
        bookingActivitiesListRepository = new BookingActivitiesListRepository(application);
        mLiveData = bookingActivitiesListRepository.getBookingActivitiesList();
    }

    public LiveData<List<BookingActivitiesList>> getBookingActivitiesList()
    {
        return mLiveData;
    }
}

我的存储库

public class BookingRepository {
   private MyDao myDao;
   private LiveData<List<BookingList>> mBookingList;
   BookingRepository(Application application){
       MyDatabase db = MyDatabase.getInstance(application);
       myDao = db.myDao();
       mBookingList = myDao.getBookingList();
   }

   LiveData<List<BookingList>> getBooking(){return mBookingList;}

我的item_view_booking_list

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardUseCompatPadding="true"
    android:elevation="5dp"
    app:cardCornerRadius="5dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        style="@style/ItemViewStyle"
        android:weightSum="1">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_weight=".85">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:drawableLeft="@drawable/ic_location_form_24dp"
                    android:drawablePadding="@dimen/dp5"
                    android:padding="5dp"
                    android:layout_weight="1"
                    android:id="@+id/from_location"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:drawableLeft="@drawable/ic_location_to_24dp"
                    android:drawablePadding="@dimen/dp5"
                    android:layout_weight="1"
                    android:padding="5dp"
                    android:id="@+id/to_location"/>


            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:layout_gravity="center"
                    android:padding="5dp"
                    android:gravity="left|center"
                    android:drawableLeft="@drawable/ic_car"
                    android:drawablePadding="@dimen/dp5"
                    android:id="@+id/cab_category"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:drawableLeft="@drawable/ic_work_black_24dp"
                    android:drawablePadding="@dimen/dp5"
                    android:layout_weight="1"
                    android:gravity="center|left"
                    android:padding="5dp"
                    android:id="@+id/package_name"/>



            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="2560"
                    android:layout_gravity="center"
                    android:drawableLeft="@drawable/ic_rupee_indian"
                    android:drawablePadding="@dimen/dp5"
                    android:padding="5dp"
                    android:gravity="left|center"
                    android:id="@+id/amount"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:gravity="center|left"
                    android:drawableLeft="@drawable/wallet"
                    android:drawablePadding="@dimen/dp5"
                    android:layout_weight="1"
                    android:padding="5dp"
                    android:id="@+id/paid_wallet_amount"/>

            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="match_parent"
                    android:padding="5dp"
                    android:layout_weight="1"
                    android:layout_gravity="center"
                    android:textStyle="bold"
                    android:drawableLeft="@drawable/ic_access_time_black_24dp"
                    android:drawablePadding="@dimen/dp5"
                    android:layout_height="wrap_content"
                    android:id="@+id/date_and_time"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:drawableLeft="@drawable/ic_date_range_black_24dp"
                    android:layout_gravity="center"
                    android:drawablePadding="@dimen/dp5"
                    android:visibility="gone"
                    android:padding="5dp"
                    android:id="@+id/no_of_day"/>


            </LinearLayout>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="plan type"
                android:layout_gravity="center"
                android:gravity="center|left"
                android:drawableLeft="@drawable/ic_work_black_24dp"
                android:drawablePadding="@dimen/dp5"
                android:layout_weight="1"
                android:padding="5dp"
                android:id="@+id/plan_type"/>



        </LinearLayout>
        <ImageView
            android:layout_width="0dp"
            android:layout_weight=".15"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/ic_send_black_24dp"
            android:id="@+id/assign_booking"
            android:visibility="visible"
            android:scaleType="centerInside"/>
        <ImageView
            android:layout_width="0dp"
            android:layout_weight=".15"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/check_black"
            android:visibility="gone"
            android:id="@+id/accept_booking"
            android:scaleType="centerInside"/>



    </LinearLayout>


</androidx.cardview.widget.CardView>

我的fragment_booking_assign xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.booking.assigned.UnassignedBooking.BookingAssignFragment">

    <!-- TODO: Update blank fragment layout -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rev_booking_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:layout_marginBottom="@dimen/dp20"
        android:scrollbarSize="@dimen/dp15"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/data_not_available"
        android:id="@+id/error_message"
        android:visibility="gone"
        android:layout_centerInParent="true"
        android:textColor="@color/red"
        android:textSize="@dimen/dimen_26dp"/>


</RelativeLayout>

解决方法

更新

在本地尝试代码后,我无法重现您的问题,唯一不同的是我模拟了数据并且未使用该服务。因此,我再次参加了您的服务课程,我想我找到了问题。在您的服务类别中,成功请求新数据后,您可以执行以下操作:

appDatabase.myDao().deleteBookingList();

mBookingList liveData被myDao更新(如您在存储库中声明的那样)时,这将导致mBookingList用空列表更新,因此recyclerView重置为空快速的瞬间==闪烁。紧接着,您用新数据填充DAO,即用新数据填充mBookingList,导致用新数据==填充当前空的recyclerView似乎滚动到顶部(但实际上发生的是从空变为空以获取完整数据)。

因此,要解决您的问题,请提出一种实现来更新数据库,而不是清除数据库并重新填充,或者避免在传入数据集为空的情况下为recyclerView设置数据。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...