1

私は解決しなければならないいくつかの問題に直面しています。だから私は地域社会の間でレルムとリサイクルの天才を参照します。 完了したタスクを2日後にToDo-Listに戻すToDo-Listを表示しています。このアプリケーションは、2つのタブ、 "TODO" & "DONE"を持つViewPagerを使用します。レルムとRecyclerViewアイテムの並べ替えと自動ViewPagerフラグメント通信

1. RecyclerView

1.1。私は2日後に、フラグメント1の完成したタスクをフラグメント0に自動的に戻したいと思っています。 問題:カウンタが0(またはそれ以下)の場合、アイテムはフラグメント0に送信されます。 次の行のアイテムをデリートすると、例外エラーが発生します。"java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling" したがって、delete関数をハンドラに追加します。 ONEが送り返された場合にのみ動作します。多くのアイテムが同時に返されると、アプリケーションがクラッシュします。私がアプリケーションを再び開くと、それはレルムに正常に保存されたのですべてが機能していますが、1つのアイテムは常に2回保存されます。 問題はどこにありますか(DoneAdapter.java)?

2.領域

2.1。 RecyclerViewにItemを追加すると同時に、Realmにアイテムを追加すると、アイテムが下部に追加されます。しかし、私は0の位置にすべての新しい項目を追加したいと思います。 (私はこのwih ArrayListを達成する方法を知っていますが、アイテムを保存して、アプリケーションを再び開くときに表示するので、Realm DBを使用しています)。 これを達成するための提案はありますか?

2.2。後でonLongClickListenerを実装して項目をドラッグ&ドロップし、Realmで位置を並べ替えることはできますか? (私はこれを使用しますhttps://www.youtube.com/watch?v=tNgevYpyA9E

2.3。私はアイテムを追加してチェックするときに素敵なアニメーションを追加したい。レルムはmRecyclerView.setItemAnimator(...);をサポートしていませんが、mAdapter.setHasStableIds(true);を追加することで可能ですと聞きました。残念ながら例外をスローする:java.lang.IllegalStateException: Cannot change whether this adapter has stable IDs while the adapter has registered observers.(私のコードでこれを見ることができます) 解決策はありますか?

(オプションで、Realmとの同期が可能なオンラインデータベース(Firebaseなど)をお勧めしますか?より一般的には、オンラインDBをレルムと同期させることができますか?チュートリアル(Udemy、YouTube)この同期プロセスを設定するには?)

最後に、完了したセクションのカウンタが自動的に更新されるように、深夜にバックグラウンドサービスを使用してデータベースを更新したいとします。誰もこれを行う方法を知っていますか?たぶんprotected void onHandleIntent(Intent intent)? また、通過時間をシミュレートするオプションがデバッグモードにあるかどうかも分かりますか?完了

MainActivity.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(); 
} 

} 

:ここ

コードです。それだけです DailyTaskRepeater

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

DoneAdapter.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(); 
} 


} 

ListItems.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 
} 

} 

ここでアプリがどのように見えるかにスクリーンショットです!もし誰かがそれを私に助けてくれたら、それは私にとって世界を意味するでしょう(特に問題1.1!)。

ありがとうございました!

答えて

3

現在のレルムのサポートでは、インデックス(タイムスタンプなど)を追加し、最新のアイテムを上部に並べ、並べ替えの効果を引き出すためにリストを並べ替えることができます。

an adapter exampleの公式レポジトリに記載されている情報を参考にしてください。

関連する問題