我有一个日历。要创建这个,我有一个日历片段,它打开了自定义日历视图
(扩展LinearLayout的类)。
然后使用MyGridAdapter
(扩展ArrayAdapter的类)构建日历。
单击日历上的某个单元格时,您将进入一个新活动,在该活动中,您可以保存一个包含一些信息(以及日历中被单击的单元格的日期)的日志。
我在我的道类中有一个查询:Log_Entries_Dao
,它被传递到LogEntriesRepository
,然后传递到LogEntriesViewModel
。
查询:
@Query(“从log_entries_table中选择日期,其中log_entries_table.date=:date”)LiveData
该查询接收日历月所有日期的列表,然后返回日志项所在的所有日期的列表。
现在,我想在我的
setupCalendar
方法中观察这个LiveData,并向我的gridAdater
类中显示日志项的日期列表,这样我就可以在所有显示日志项的单元格中添加圆圈。
问题是,我认为在
CustomCalendarView
(LinearLayout类)中使用我的LogViewModel
类是不好的做法。如何正确地查询我的数据库、观察liveData并从我的setUpCalendar方法中将其发送到我的适配器?
日历片段
public class CalendarFragment extends Fragment {
CustomCalendarView customCalendarView;
List<Date> dates = new ArrayList<>();
LogEntriesViewModel logEntriesViewModel;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.calendar_activity_main, container,false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
customCalendarView =(CustomCalendarView) getView().findViewById(R.id.custom_calendar_view);
((AppCompatActivity) getActivity()).getSupportActionBar().hide();
}
}
自定义日历视图
public class CustomCalendarView extends LinearLayout {
ImageButton NextButton, PreviousButton;
TextView CurrentDate;
GridView gridView;
public static final int MAX_CALENDAR_DAYS = 42;
Calendar calendar = Calendar.getInstance(Locale.ENGLISH);
Context context;
MyGridAdapter myGridAdapter;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM yyyy", Locale.ENGLISH);
SimpleDateFormat monthFormat = new SimpleDateFormat("MMMM", Locale.ENGLISH);
SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy", Locale.ENGLISH);
SimpleDateFormat eventDateFormat = new SimpleDateFormat(("dd-MM-yyyy"), Locale.ENGLISH);
public static final String MY_PREFS_NAME = "MyPrefsFile";
List<Date> dates = new ArrayList<>();
List<Log_Entries> eventsList = new ArrayList<>();
public CustomCalendarView(Context context) {
super(context);
}
public CustomCalendarView(final Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
InitializeLayout();
SetUpCalendar();
PreviousButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
calendar.add(Calendar.MONTH, -1);
SetUpCalendar();
}
});
NextButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
calendar.add(Calendar.MONTH, 1);
SetUpCalendar();
}
});
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
final String date = eventDateFormat.format(dates.get(position));
Intent i = new Intent(getContext(), WorkoutButtonsActivity.class);
i.putExtra(WorkoutButtonsActivity.EXTRA_DATE, date);
getContext().startActivity(i);
}
});
}
public CustomCalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void InitializeLayout() {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.calendar_layout, this);
NextButton = view.findViewById(R.id.nextBtn);
PreviousButton = view.findViewById(R.id.previousBtn);
CurrentDate = view.findViewById(R.id.current_Date);
gridView = view.findViewById(R.id.gridview);
}
private void SetUpCalendar() {
String currentDate = dateFormat.format(calendar.getTime());
CurrentDate.setText(currentDate);
dates.clear();
Calendar monthCalendar = (Calendar) calendar.clone();
monthCalendar.set(Calendar.DAY_OF_MONTH, 1);
int FirstDayofMonth = monthCalendar.get(Calendar.DAY_OF_WEEK) - 1;
monthCalendar.add(Calendar.DAY_OF_MONTH, -FirstDayofMonth);
while (dates.size() < MAX_CALENDAR_DAYS) {
dates.add(monthCalendar.getTime());
monthCalendar.add(Calendar.DAY_OF_MONTH, 1);
}
myGridAdapter = new MyGridAdapter(context, dates, calendar, eventsList);
gridView.setAdapter(myGridAdapter);
}
}
MyGridAdapter
public class MyGridAdapter extends ArrayAdapter {
List<Date> dates;
Calendar currentDate;
List<Log_Entries> logs;
LayoutInflater inflater;
public MyGridAdapter(@NonNull Context context, List<Date> dates, Calendar currentDate, List<Log_Entries> logs){
super(context, R.layout.single_cell_layout);
this.dates = dates;
this.currentDate = currentDate;
this.logs = logs;
inflater = LayoutInflater.from(context);
Log.i("dates", String.valueOf(dates));
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Date monthDate = dates.get(position);
Calendar dateCalendar = Calendar.getInstance();
dateCalendar.setTime(monthDate);
int DayNo = dateCalendar.get(Calendar.DAY_OF_MONTH);
int displayMonth = dateCalendar.get(Calendar.MONTH) +1;
int displayYear = dateCalendar.get(Calendar.YEAR);
int currentMonth = currentDate.get(Calendar.MONTH) + 1;
int currentYear = currentDate.get(Calendar.YEAR);
int currentDay = currentDate.get(Calendar.DAY_OF_MONTH);
View view = convertView;
if (view == null){
view = inflater.inflate(R.layout.single_cell_layout, parent,false);
}
if (displayMonth == currentMonth && displayYear == currentYear){
view.setBackgroundColor(getContext().getResources().getColor(R.color.green));
}
else{
view.setBackgroundColor(Color.parseColor("#cccccc"));
}
TextView Day_Number = view.findViewById(R.id.calendar_day);
Day_Number.setText(String.valueOf(DayNo));
Calendar eventCalendar = Calendar.getInstance();
if(DayNo == currentDay && displayMonth == eventCalendar.get(Calendar.MONTH) + 1 && displayYear == eventCalendar.get(Calendar.YEAR)){
Day_Number.setTextColor(Color.parseColor("#FFFF33"));
}
ArrayList<String> arrayList = new ArrayList<>();
for (int i = 0; i < logs.size(); i++){
}
return view;
}
@Override
public int getCount() {
return dates.size();
}
@Override
public int getPosition(@Nullable Object item) {
return dates.indexOf(item);
}
@Nullable
@Override
public Object getItem(int position) {
return dates.get(position);
}
}
LogEntriesRepository
public class LogEntriesRepository {
private Log_Entries_Dao log_entries_dao;
private LiveData<List<Log_Entries>> allLogEntries;
private LiveData<List<Log_Entries>> allWorkoutLogEntries;
private LiveData<List<LogDates>> allDatesWithLog;
public LogEntriesRepository(Application application) {
ExerciseDatabase database = ExerciseDatabase.getInstance(application);
log_entries_dao = database.log_entries_dao();
allLogEntries = log_entries_dao.getAllFromLogEntries();
}
public void insert(Log_Entries log_entries) {
new InsertLogEntryAsyncTask(log_entries_dao).execute(log_entries);
}
public void update(Log_Entries log_entries) {
new UpdateLogEntryAsyncTask(log_entries_dao).execute(log_entries);
}
public void delete(Log_Entries log_entries) {
new DeleteLogEntryAsyncTask(log_entries_dao).execute(log_entries);
}
public LiveData<List<Log_Entries>> getAllLogEntries() {
return allLogEntries;
}
public LiveData<List<Log_Entries>> getAllWorkoutLogEntries(int junctionID, String date) {
allWorkoutLogEntries = log_entries_dao.getAllFromWorkoutLogEntries(junctionID, date);
return allWorkoutLogEntries;
}
public LiveData<List<LogDates>> getAllDateLogEntries(List<String> date) {
allDatesWithLog = log_entries_dao.getAllDatesWithLogs(date);
return allDatesWithLog;
}
private static class InsertLogEntryAsyncTask extends AsyncTask<Log_Entries, Void, Void> {
private Log_Entries_Dao log_entries_dao;
private InsertLogEntryAsyncTask(Log_Entries_Dao log_entries_dao) {
this.log_entries_dao = log_entries_dao;
}
@Override
protected Void doInBackground(Log_Entries... log_entries) {
log_entries_dao.insert(log_entries[0]);
return null;
}
}
private static class UpdateLogEntryAsyncTask extends AsyncTask<Log_Entries, Void, Void> {
private Log_Entries_Dao log_entries_dao;
private UpdateLogEntryAsyncTask(Log_Entries_Dao log_entries_dao) {
this.log_entries_dao = log_entries_dao;
}
@Override
protected Void doInBackground(Log_Entries... log_entries) {
log_entries_dao.update(log_entries[0]);
return null;
}
}
private static class DeleteLogEntryAsyncTask extends AsyncTask<Log_Entries, Void, Void> {
private Log_Entries_Dao log_entries_dao;
private DeleteLogEntryAsyncTask(Log_Entries_Dao log_entries_dao) {
this.log_entries_dao = log_entries_dao;
}
@Override
protected Void doInBackground(Log_Entries... log_entries) {
log_entries_dao.delete(log_entries[0]);
return null;
}
}
}
LogEntriesViewModel
public class LogEntriesViewModel extends AndroidViewModel {
private LogEntriesRepository repository;
private LiveData<List<Log_Entries>> allLogEntries;
private LiveData<List<Log_Entries>> allWorkoutLogEntries;
private LiveData<List<LogDates>> allDateLogEntries;
public LogEntriesViewModel(@NonNull Application application) {
super(application);
repository = new LogEntriesRepository(application);
allLogEntries = repository.getAllLogEntries();
}
public void insert(Log_Entries log_entries){
repository.insert(log_entries);
}
public void update(Log_Entries log_entries){
repository.update(log_entries);
}
public void delete(Log_Entries log_entries ) {
repository.delete(log_entries);
}
// public LiveData<List<Log_Entries>> getAllLogs(){
// return allLogEntries;
// }
public LiveData<List<Log_Entries>> getAllWorkoutLogEntries(int junctionID, String date){
allWorkoutLogEntries = repository.getAllWorkoutLogEntries(junctionID, date);
return allWorkoutLogEntries;
}
public LiveData<List<LogDates>> getAllDateLogEntries(List<String> date){
allDateLogEntries = repository.getAllDateLogEntries(date);
return allDateLogEntries;
}
}
我希望如果你理解这一点并应用到你的代码中,如果我没有错的话,这将解决你的问题。我没有通读您的所有代码,但我得到了您的查询,即“如何将Livedata设置为适配器”,下面是解决方案。
这里是您可以与您的参考代码进行比较的参考代码。
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY lastName ASC")
public abstract LiveData<List<User>> usersByLastName();
}
class MyViewModel extends ViewModel {
public final LiveData<List<User>> usersList;
public MyViewModel(UserDao userDao) {
usersList = userDao.usersByLastName();
}
}
class MyActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
RecyclerView recyclerView = findViewById(R.id.user_list);
UserAdapter<User> adapter = new UserAdapter();
viewModel.usersList.observe(this, list -> adapter.submitList(list));
recyclerView.setAdapter(adapter);
}
}
class UserAdapter extends ListAdapter<User, UserViewHolder> {
public UserAdapter() {
super(User.DIFF_CALLBACK);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
holder.bindTo(getItem(position));
}
public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK =
new DiffUtil.ItemCallback<User>() {
@Override
public boolean areItemsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// User properties may have changed if reloaded from the DB, but ID is fixed
return oldUser.getId() == newUser.getId();
}
@Override
public boolean areContentsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// NOTE: if you use equals, your object must properly override
Object#equals()
// Incorrectly returning false here will result in too many animations.
return oldUser.equals(newUser);
}
}
}
在摘要中,
在Dao中的第一步:
public abstract LiveData<List<User>> usersByLastName();
在ViewModel中执行第2步:
public final LiveData<List<User>> usersList;
usersList = userDao.usersByLastName();
最后在你的活动/片段中:
UserAdapter<User> adapter = new UserAdapter();
viewModel.usersList.observe(this, list -> adapter.submitList(list));
recyclerView.setAdapter(adapter);
尝试以下通用模式:
我希望能有所帮助
此外,为什么Viewmodel不能观察到它自己的LiveData的变化?
使用RxJS如何在观察者上传递新属性?所以基本上我希望道具“customProp”可以被观察到 添加更多的信息-所以基本上,我试图创建一个冷可观察的,其中制片人需要一个道具,应该来自订户 添加用法信息--coldObservable是DB连接函数,customProp是需要在DB上执行的查询
问题是: 使用及其其他功能不是更好吗?
组件具有变量作为观察者: 当
我有一个单独的类来处理数据提取(特别是Firebase),我通常从它返回LiveData对象并异步更新它们。现在我希望将返回的数据存储在ViewModel中,但问题是为了获得所述值,我需要观察从数据提取类返回的LiveData对象。observe方法需要一个LifecycleOwner对象作为第一个参数,但我的ViewModel中显然没有这个对象,而且我知道我不应该在ViewModel中保留对ac