gpt4 book ai didi

android - Realm 和 RecyclerView Item 排序和自动 ViewPager Fragment 通信

转载 作者:行者123 更新时间:2023-11-29 17:20:47 25 4
gpt4 key购买 nike

一段时间以来,我一直面临一些无法解决的问题。所以我指的是社区中的 Realm 和 RecyclerView 天才。我正在处理一个 ToDo-List,它在 2 天后将已完成的任务设置回 ToDo-List。该应用程序使用带有两个选项卡的 ViewPager:“TODO”和“DONE”。

<强>1。 RecyclerView

1.1。我希望 fragment 1 中完成的任务在 2 天后自动发送回 fragment 0。问题:如果计数器为 0(或更低),则项目将被发送到 fragment 0。如果我删除下一行中的项目,我会收到异常错误:"java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling"所以我把删除函数放到一个处理程序中。然后,只有当 ONE 被发回时,它才能正常工作。如果许多项目同时被发回,应用程序就会崩溃。当我重新打开应用程序时,一切正常,因为它已成功保存在 Realm 中,但一个项目总是保存两次。问题出在哪里(在 DoneAdapter.java 中)?

<强>2。 Realm

2.1。当我将一个项目添加到 RecyclerView(并同时添加到 Realm)时,该项目被添加到底部。但我想在位置 0 添加每个新项目。(我知道如何使用 ArrayList 实现此目的,但我希望在重新打开应用程序时存储和显示这些项目,所以我使用的是 Realm DB。)您对实现这一目标有什么建议吗?

2.2。是否可以稍后在 onLongClickListener 上实现用于拖放项目并重新排列 Realm 的位置?(我想用这个 https://www.youtube.com/watch?v=tNgevYpyA9E )

2.3。我想在添加和检查项目时添加一些漂亮的动画。 Realm 不支持 mRecyclerView.setItemAnimator(...); 但我听说可以通过添加 mAdapter.setHasStableIds(true); 来实现。不幸的是,它抛出一个异常:java.lang.IllegalStateException: Cannot change whether this adapter has stable IDs while the adapter has registered observers.(你可以在我下面的代码中看到这一点)您对此有什么解决方案吗?

(可选 1.4。你能推荐我可以与 Realm 同步的任何在线数据库(例如 Firebase)吗?或者更一般地说:是否可以将在线数据库与 Realm 同步?你知道任何教程(Udemy,YouTube)吗?设置此同步过程?)

最后:我想在每个午夜用后台服务更新数据库,因此已完成部分中的计数器会自动更新。有谁也知道该怎么做?也许使用 protected void onHandleIntent(Intent intent)?您是否也知道在 Debug模式下是否有模拟流逝时间的选项?

代码如下:

主 Activity .java

public class MainActivity extends AppCompatActivity implements ToOtherFragmentCommunicator {


private ViewPagerAdapter mViewPagerAdapter;
private ViewPager mViewPager;
private static final int DONE = 1;
private static final int TODO = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);


mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mViewPagerAdapter);

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {

}

@Override
public void onTabReselected(TabLayout.Tab tab) {

}
});

RealmConfiguration configuration = new RealmConfiguration.Builder(this).build();
Realm.setDefaultConfiguration(configuration);
}

@Override
public void itemToOtherFragment(String data, int fragment) {
if (DONE == fragment) {
Done done = (Done) mViewPagerAdapter.getItem(fragment);
done.createDoneItem(data);
} else if (TODO == fragment) {
ToDo toDo = (ToDo) mViewPagerAdapter.getItem(fragment);
toDo.createToDoItem(data);
}
}
}

ToDo.java

public class ToDo extends Fragment {

private RecyclerView mRecyclerView;
private ToDoAdapter mAdapter;
private EditText taskInput;
private String taskName;
private Realm mRealm;
private RealmResults<ListItems> mResults;


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View toDoView = inflater.inflate(R.layout.todo_layout, container, false);

mRecyclerView = (RecyclerView) toDoView.findViewById(R.id.todo_rv);


mRealm = Realm.getDefaultInstance();
mResults = mRealm.where(ListItems.class).equalTo("fragment", 0).findAllAsync();

setRecyclerView();

mRecyclerView.setItemAnimator(null);

//TODO add product to shopping list
final Handler handler = new Handler();
taskInput = (EditText) toDoView.findViewById(R.id.task_input);
taskInput.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (taskInput.getText().length() > 0 && (event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
// Perform action on key press
taskName = taskInput.getText().toString();

//Problem 2.1
//Code for adding item at the top with mRealm?
mRealm.beginTransaction();
createToDoItem(taskName);
mRealm.commitTransaction();


// mRecyclerView.scrollToPosition(0);
taskInput.setText(null);

handler.postDelayed(new Runnable() {
@Override
public void run() {
taskInput.setFocusableInTouchMode(true);
taskInput.setFocusable(true);
taskInput.requestFocus();
}
}, 200);

return true;

} else if (taskInput.length() == 0 && (event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
taskInput.clearFocus();
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(taskInput.getWindowToken(), 0);
return true;
}

return false;

}
});

return toDoView;
}


//TODO creates the shopping list item in DB
public void createToDoItem(String taskName) {

ListItems item = mRealm.createObject(ListItems.class);

long now = System.currentTimeMillis();
item.setAddedTime(now);
item.setFragment(0);

item.setTaskName(taskName);

mRealm.copyToRealmOrUpdate(item);
}

public void setRecyclerView() {
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new ToDoAdapter(getActivity(), mRealm, mResults);
mRecyclerView.setAdapter(mAdapter);

//Problem 2.3.
//Produces "java.lang.IllegalStateException: Cannot change whether this adapter has stable IDs while the adapter has registered observers."
// mAdapter.setHasStableIds(true);
}

private RealmChangeListener mChangeListener = new RealmChangeListener() {
@Override
public void onChange() {
mAdapter.updateItems(mResults);
}
};

@Override
public void onStart() {
super.onStart();
mResults.addChangeListener(mChangeListener);
}

@Override
public void onStop() {
super.onStop();
mResults.removeChangeListener(mChangeListener);
}


}

ToDoAdapter.java

public class ToDoAdapter extends RecyclerView.Adapter<ListItemsViewHolder> {

private Context mContext;
private Realm mRealm;
private RealmResults<ListItems> mResults;
private int focusedItem = 0;
ToOtherFragmentCommunicator comm;

ToDoAdapter(Context context, Realm realm, RealmResults<ListItems> mResults) {
this.mContext = context;
this.mRealm = realm;
updateItems(mResults);
}

public void updateItems(RealmResults<ListItems> mResults) {
this.mResults = mResults;
notifyDataSetChanged();
}

//Problem 2.3.
//needed for mAdapter.setHasStableIds(true); in ToDo.java
// @Override
// public long getItemId(int position) {
// if (position < mResults.size()) {
// return mResults.get(position).getAddedTime();
// } else {
// return RecyclerView.NO_ID;
// }
// }

@Override
public ListItemsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.todo_item, parent, false);
comm = (ToOtherFragmentCommunicator) mContext;
return new ListItemsViewHolder(v);

}

@Override
public void onBindViewHolder(final ListItemsViewHolder holder, final int position) {
final ListItems items = mResults.get(position);


holder.taskName.setText(items.getTaskName());

holder.itemView.setSelected(focusedItem == position);
holder.getLayoutPosition();

holder.itemCheckbox.setOnCheckedChangeListener(null);
holder.itemCheckbox.setChecked(items.isSelected());

holder.itemCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

mRealm.beginTransaction();
items.setSelected(isChecked);

//send item to Done
comm.itemToOtherFragment(items.getTaskName(), 1);

removeItem(position);
mRealm.commitTransaction();

}
});


}


@Override
public int getItemCount() {
return (mResults != null ? mResults.size() : 0);
}

private void removeItem(int position) {
mResults.get(position).removeFromRealm();
notifyDataSetChanged();
}

}

完成.java

public class Done extends Fragment {

private RecyclerView mRecyclerView;
private DoneAdapter mAdapter;
private Calendar calendar = Calendar.getInstance();
private Date date = new Date();
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
private Realm mRealm;
private RealmResults<ListItems> mResults;


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View doneView = inflater.inflate(R.layout.done_layout, container, false);

mRecyclerView = (RecyclerView) doneView.findViewById(R.id.done_rv);

mRealm = Realm.getDefaultInstance();
mResults = mRealm.where(ListItems.class).equalTo("fragment", 1).findAllAsync();

setRecyclerView();
mRecyclerView.setItemAnimator(null);


return doneView;
}


//TODO creates the fridge item in DB
public void createDoneItem(String taskName) {
TimeZone.getDefault();


ListItems item = mRealm.createObject(ListItems.class);

long now = System.currentTimeMillis();
item.setAddedTime(now);
item.setFragment(1);

item.setTaskName(taskName);
item.setInputDate(simpleDateFormat.format(calendar.getTime()));

calendar.add(Calendar.DATE, 2);
item.setRenewDate(simpleDateFormat.format(calendar.getTime()));


//reset time to current date after adding days
calendar.setTime(date);

item.getRenewDate();

mRealm.copyToRealmOrUpdate(item);
}


public void setRecyclerView() {
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new DoneAdapter(getActivity(), mRealm, mResults, Done.this);
mRecyclerView.setAdapter(mAdapter);
}


private RealmChangeListener mChangeListener = new RealmChangeListener() {
@Override
public void onChange() {
mAdapter.updateItems(mResults);
}
};

@Override
public void onStart() {
super.onStart();
mResults.addChangeListener(mChangeListener);
}

@Override
public void onStop() {
super.onStop();
mResults.removeChangeListener(mChangeListener);
}
}

完成适配器.java

public class DoneAdapter extends RecyclerView.Adapter<ListItemsViewHolder> {

private Context mContext;
private Done done;
private Realm mRealm;
private RealmResults<ListItems> mResults;
private int focusedItem = 0;
protected ToOtherFragmentCommunicator comm;


DoneAdapter(Context context, Realm realm, RealmResults<ListItems> results, Done done) {
this.mContext = context;
this.mRealm = realm;
this.done = done;

updateItems(results);
}

public void updateItems(RealmResults<ListItems> mResults) {
this.mResults = mResults;
notifyDataSetChanged();
}

@Override
public ListItemsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.done_item, parent, false);
comm = (ToOtherFragmentCommunicator) mContext;
return new ListItemsViewHolder(v);
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onBindViewHolder(final ListItemsViewHolder holder, final int position) {
final ListItems items = mResults.get(position);

holder.taskName.setText(items.getTaskName());

try {
if (items.getRenewCounter() == 1) {
holder.renewCounter.setText(mContext.getString(R.string.show_days_till_renew, items.getRenewCounter(), mContext.getString(R.string.day)));
} else {
holder.renewCounter.setText(mContext.getString(R.string.show_days_till_renew, items.getRenewCounter(), mContext.getString(R.string.days)));
}

holder.renewCounter.setTextColor(ContextCompat.getColor(mContext, R.color.colorAccent));
if (items.getRenewCounter() <= 0) {
mRealm.beginTransaction();

//Problem 1.1.
//send item back to todo list
comm.itemToOtherFragment(items.getTaskName(), 0);
// Produces "java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling" if there is no Handler
Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {

mRealm.beginTransaction();
removeItem(position);
mRealm.commitTransaction();

}
};
handler.post(r);
mRealm.commitTransaction();
}


} catch (ParseException e) {
e.printStackTrace();
}


holder.itemView.setSelected(focusedItem == position);
holder.getLayoutPosition();

}


@Override
public int getItemCount() {
return (mResults != null ? mResults.size() : 0);
}

private void removeItem(int position) {
mResults.get(position).removeFromRealm();
notifyDataSetChanged();
}


}

列表项.java

public class ListItems extends RealmObject {

public ListItems(long addedTime, String taskName, String inputDate, String renewDate, int fragment) {
this.addedTime = addedTime;
this.taskName = taskName;
this.inputDate = inputDate;
this.renewDate = renewDate;
this.fragment = fragment;
}

@PrimaryKey
private long addedTime;
private int fragment;
@Ignore
private long renewCounter;
private String taskName, inputDate, renewDate;
private boolean selected;

public ListItems() {
}

public long getAddedTime() {
return addedTime;
}

public void setAddedTime(long addedTime) {
this.addedTime = addedTime;
}

public int getFragment() {
return fragment;
}

public void setFragment(int fragment) {
this.fragment = fragment;
}

public String getTaskName() {
return taskName;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public String getInputDate() {
return inputDate;
}

public void setInputDate(String inputDate) {
this.inputDate = inputDate;
}

public String getRenewDate() {
return renewDate;
}

public void setRenewDate(String renewDate) {
this.renewDate = renewDate;
}

public boolean isSelected() {
return selected;
}

public void setSelected(boolean selected) {
this.selected = selected;
}

public long getRenewCounter() throws ParseException {
TimeZone.getDefault();

SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
Date todayDate = new Date();
Date exDate = dateFormat.parse(renewDate);

this.renewCounter = daysBetween(todayDate, exDate);
return renewCounter;

}

private static long daysBetween(Date startDate, Date endDate) {
Calendar sDate = getDatePart(startDate);
Calendar eDate = getDatePart(endDate);

long daysBetween = 0;
while (sDate.before(eDate)) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}

while (eDate.before(sDate)) {
eDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween--;
}

return daysBetween;
}

private static Calendar getDatePart(Date date) {
Calendar cal = Calendar.getInstance(); // get calendar instance
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight
cal.set(Calendar.MINUTE, 0); // set minute in hour
cal.set(Calendar.SECOND, 0); // set second in minute
cal.set(Calendar.MILLISECOND, 0); // set millisecond in second

return cal; // return the date part
}

}

这是应用程序外观的屏幕截图: DailyTaskRepeater

就是这样!如果有人可以帮助我解决所有这些问题(尤其是问题 1.1!),这对我来说意义重大。

谢谢!

最佳答案

目前 Realm 支持的做法是添加一个索引(例如时间戳)并反向排序您的列表,以使最新项目位于顶部并实现您正在寻求的重新排列效果。

请考虑引用 an adapter example在官方存储库中提供。

关于android - Realm 和 RecyclerView Item 排序和自动 ViewPager Fragment 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36664262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com