问题描述
我必须实时显示数据。所以我创建了一个服务并添加了一个计时器。我每隔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设置数据。