2016-11-09 10 views
2

私はAndroidが初めてですが、いくつかのチュートリアルを読んだ後、RecyclerViewを使ってレルムのデータをRealmRecyclerViewAdapterに拡張して簡単なアプリを書くことができました。
デフォルトのアニメーターには安定したIDが必要なので、自分のエンティティに固有のIDを追加しました。ドラッグアンドドロップを除くすべてが正常に動作するようです(削除、追加、すべての領域操作)。まあ、それはデータとUIが一貫しているが、アニメーションが変わって見えるという意味の作品で、アイテムを1つだけ下に移動できます。
絵はそうここにある千個の言葉の価値がある:
enter image description hereRecyclerViewレルムベースのアダプタでドラッグ&ドロップ

私はまた、コードを貼り付ける必要がありますね。私は可能な限り短くしようとしました。

public class MainActivity extends AppCompatActivity implements OnStartDragListener { 
    private ItemTouchHelper touchHelper; 
    private Realm realm; 
    private TestRecyclerViewAdapter adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // Irrelevant init stuff stripped 

     RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 
     recyclerView.setHasFixedSize(true); 
     recyclerView.setLayoutManager(new LinearLayoutManager(this)); 
     recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); 

     adapter = new TestRecyclerViewAdapter(this, realm.where(Item.class) 
                 .findAll() 
                 .sort(Item.INDEX)); 
     recyclerView.setAdapter(adapter); 

     ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(adapter); 
     touchHelper = new ItemTouchHelper(callback); 
     touchHelper.attachToRecyclerView(recyclerView); 
    } 

    @Override 
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) { 
     touchHelper.startDrag(viewHolder); 
    } 

    // not sure how this method should be implemented 
    public void moveItem(Item item, final int fromPosition, final int toPosition) { 
     final int index = item.index; 
     realm.executeTransaction(new Realm.Transaction() { 
      @Override 
      public void execute(Realm realm) { 
       Item item = realm.where(Item.class).equalTo(Item.INDEX, index).findFirst(); 
       if (fromPosition < toPosition) { 
        RealmResults<Item> results = realm.where(Item.class) 
                 .greaterThan(Item.INDEX, fromPosition) 
                 .lessThanOrEqualTo(Item.INDEX, toPosition) 
                 .findAll(); 
        for (int i = 0; i < results.size(); i++) { 
         results.get(i).index -= 1; 
        } 
       } else { 
        RealmResults<Item> results = realm.where(Item.class) 
                 .greaterThanOrEqualTo(Item.INDEX, toPosition) 
                 .lessThan(Item.INDEX, fromPosition) 
                 .findAll(); 
        for (int i = 0; i < results.size(); i++) { 
         results.get(i).index += 1; 
        } 
       } 
       item.index = toPosition; 
      } 
     }); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     realm.close(); 
    } 
} 

­

public class Item extends RealmObject { 
    public static final String INDEX = "index"; 
    public static final String TEXT = "text"; 
    public static final String ID = "id"; 

    @PrimaryKey 
    public long id; 
    @Index 
    public int index; 
    public String text; 
} 

­

interface OnStartDragListener { 
    void onStartDrag(RecyclerView.ViewHolder viewHolder); 
} 

­

class TestRecyclerViewAdapter extends RealmRecyclerViewAdapter<Item, 
     TestRecyclerViewAdapter.EditInfoViewHolder> implements ItemTouchHelperAdapter { 

    private final static String TAG = TestRecyclerViewAdapter.class.getName(); 
    private final MainActivity activity; 

    public TestRecyclerViewAdapter(@NonNull MainActivity activity, @Nullable 
      OrderedRealmCollection<Item> data) { 
     super(activity, data, true); 
     this.activity = activity; 
     setHasStableIds(true); 
    } 

    @Override 
    public long getItemId(int index) { 
     return getData().get(index).id; 
    } 

    @Override 
    public EditInfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = inflater.inflate(R.layout.item, parent, false); 
     return new EditInfoViewHolder(view); 
    } 

    @Override 
    public void onBindViewHolder(final EditInfoViewHolder holder, int position) { 
     Item obj = getData().get(position); 
     holder.data = obj; 
     holder.text.setText(obj.text); 
     holder.handle.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { 
        activity.onStartDrag(holder); 
       } 
       return false; 
      } 
     }); 
    } 

    @Override 
    public boolean onItemMove(int fromPosition, int toPosition) { 
     activity.moveItem(getData().get(fromPosition), fromPosition, toPosition); 
     notifyItemMoved(fromPosition, toPosition); 
     return true; 
    } 

    class EditInfoViewHolder extends RecyclerView.ViewHolder { 
     final TextView text; 
     final ImageView handle; 

     public Item data; 
     public EditInfoViewHolder(View itemView) { 
      super(itemView); 
      text = (TextView) itemView.findViewById(R.id.text); 
      handle = (ImageView) itemView.findViewById(R.id.handle); 
     } 

    } 
} 

­

interface ItemTouchHelperAdapter { 
    boolean onItemMove(int fromPosition, int toPosition); 
} 

­

class ItemTouchHelperCallback extends ItemTouchHelper.Callback { 

    private final ItemTouchHelperAdapter adapter; 

    public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { 
     this.adapter = adapter; 
    } 

    @Override 
    public boolean isItemViewSwipeEnabled() { 
     return true; 
    } 

    @Override 
    public boolean isLongPressDragEnabled() { 
     return false; 
    } 

    @Override 
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
     int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; 
     int swipeFlags = 0; 
     return makeMovementFlags(dragFlags, swipeFlags); 
    } 

    @Override 
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { 
     if (source.getItemViewType() != target.getItemViewType()) { 
      return false; 
     } 
     adapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition()); 
     return true; 
    } 

    @Override 
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 
    } 
} 

私はこのコードの量を掲示するためにとても罪悪感を感じる...

答えて

1

あなたの問題はRealmRecyclerViewAdapterがすべて上書きされますadapter.notifyDataSetChanged()を呼び出すRealmChangeListenerを、登録しているという事実から茎RecyclerViewアニメーション。

通常のRecyclerViewAdapterを使用し、UIスレッドのトランザクションを使用してレルムの要素を操作すると、回避方法としてforce a refresh immediately afterwardsが発生する可能性があります。

class TestRecyclerViewAdapter extends RecyclerView.Adapter<...> { 

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
    activity.moveItem(getData().get(fromPosition), fromPosition, toPosition); // <-- refresh in there 
    notifyItemMoved(fromPosition, toPosition); 
    return true; 
} 

public void moveItem(Item item, final int fromPosition, final int toPosition) { 
    final int index = item.index; 
    realm.executeTransaction(new Realm.Transaction() { 
     @Override 
     public void execute(Realm realm) { 
      Item item = realm.where(Item.class).equalTo(Item.INDEX, index).findFirst(); 
      if (fromPosition < toPosition) { 
       RealmResults<Item> results = realm.where(Item.class) 
                .greaterThan(Item.INDEX, fromPosition) 
                .lessThanOrEqualTo(Item.INDEX, toPosition) 
                .findAll(); 
       for (int i = 0; i < results.size(); i++) { 
        results.get(i).index -= 1; 
       } 
      } else { 
       RealmResults<Item> results = realm.where(Item.class) 
                .greaterThanOrEqualTo(Item.INDEX, toPosition) 
                .lessThan(Item.INDEX, fromPosition) 
                .findAll(); 
       for (int i = 0; i < results.size(); i++) { 
        results.get(i).index += 1; 
       } 
      } 
      item.index = toPosition; 
     } 
    }); 
    RealmRefresh.refreshRealm(realm); 
} 

RealmRefreshは同期実行するために、すべての非同期クエリを強制する、ともあなたは他の場所(バックグラウンドスレッドなど)を実行、このような取引から自動更新を得ることはありません。しかし、私はそれが動作すると思います!

+0

私はあなたのアドバイスを取ったが、少し違ったことをした。私は定期的な 'RecyclerViewAdapter'を使用し、レルム操作をアダプターに移しました。これまでのところ動作しています。 – Przeszczep

関連する問題