无法从我的模型类更新RecyclerView?

时间:2016-03-12 06:43:48

标签: android android-recyclerview recycler-adapter notifydatasetchanged

我正在使用RecyclerView,它必须是Draggable&滑动式。一切都很完美。

数据正在一个名为ExerciseDataProvider&的班级中被提取。 RV代码是另一个片段RecyclerListViewFragment

问题是我无法通过postExecute方法通知FetchExercise更改的数据。因此,数据不会在RV中填充。

请指导我正确的方向。

活性

    public class DraggableSwipeableExampleActivity extends AppCompatActivity {
        private static final String FRAGMENT_TAG_DATA_PROVIDER = "data provider";
        private static final String FRAGMENT_LIST_VIEW = "list view";
        private static final String FRAGMENT_TAG_ITEM_PINNED_DIALOG = "item pinned dialog";

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

            if (savedInstanceState == null) {
                getSupportFragmentManager().beginTransaction()
                        .add(new ExampleDataProviderFragment(), FRAGMENT_TAG_DATA_PROVIDER)
                        .commit();
                getSupportFragmentManager().beginTransaction()
                        .add(R.id.container, new RecyclerListViewFragment(), FRAGMENT_LIST_VIEW)
                        .commit();
            }
        }

 public AbstractDataProvider getDataProvider() {
        final Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DATA_PROVIDER);
        return ((ExampleDataProviderFragment) fragment).getDataProvider();
    }

DATA PROVIDER

public class ExerciseDataProvider extends AbstractDataProvider {
    private List<ConcreteData> mData;
    private ConcreteData mLastRemovedData;
    private int mLastRemovedPosition = -1;

    public ExerciseDataProvider() {
        new FetchExercise().execute();
        mData = new LinkedList<>();
    }

    class FetchExercise extends AsyncTask<Void,Void,Void> {

        @Override
        protected Void doInBackground(Void... params) {
            final int viewType = 0;
            final int swipeReaction = RecyclerViewSwipeManager.REACTION_CAN_SWIPE_UP | RecyclerViewSwipeManager.REACTION_CAN_SWIPE_DOWN;

            String url = "https://gist.githubusercontent.com/fake/cb9aa5494e7ee36ac3ca/raw/a4abfd19368063/exercise.JSON";
            Log.d("Path", url);
            try {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder().url(url).build();
                Response response = client.newCall(request).execute();
                String jsonData = response.body().string();
                try {
                    JSONArray jsonArray = new JSONArray(jsonData);
                    for (int i = 0; i < jsonArray.length(); i++) {
                        final long id = i;
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        String exercise_name = jsonObject.getString("name");
                        int exercise_duration = jsonObject.getInt("duration");

                        mData.add(new ConcreteData(id, viewType, exercise_name, exercise_duration, swipeReaction));
                        Log.d("exercise_name", exercise_name);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
        }
    }


    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public Data getItem(int index) {
        if (index < 0 || index >= getCount()) {
            throw new IndexOutOfBoundsException("index = " + index);
        }

        return mData.get(index);
    }

    @Override
    public int undoLastRemoval() {
        if (mLastRemovedData != null) {
            int insertedPosition;
            if (mLastRemovedPosition >= 0 && mLastRemovedPosition < mData.size()) {
                insertedPosition = mLastRemovedPosition;
            } else {
                insertedPosition = mData.size();
            }

            mData.add(insertedPosition, mLastRemovedData);

            mLastRemovedData = null;
            mLastRemovedPosition = -1;

            return insertedPosition;
        } else {
            return -1;
        }
    }

    @Override
    public void moveItem(int fromPosition, int toPosition) {
        if (fromPosition == toPosition) {
            return;
        }

        final ConcreteData item = mData.remove(fromPosition);
        mData.add(toPosition, item);
        mLastRemovedPosition = -1;
    }

    @Override
    public void removeItem(int position) {
        //noinspection UnnecessaryLocalVariable
        final ConcreteData removedItem = mData.remove(position);

        mLastRemovedData = removedItem;
        mLastRemovedPosition = position;
    }

    public static final class ConcreteData extends Data {

        private final long mId;
        private final String mText;
        private final int mViewType;
        private final int mDuration;
        private boolean mPinned;

        ConcreteData(long id, int viewType, String text, int duration, int swipeReaction) {
            mId = id;
            mViewType = viewType;
            mText = text;
            mDuration = duration;
        }

        @Override
        public int getViewType() {
            return mViewType;
        }

        @Override
        public int getDuration() {
            return mDuration;
        }

        @Override
        public long getId() {
            return mId;
        }

        @Override
        public String toString() {
            return mText;
        }

        @Override
        public String getText() {
            return mText;
        }

        @Override
        public boolean isPinned() {
            return mPinned;
        }

        @Override
        public void setPinned(boolean pinned) {
            mPinned = pinned;
        }

    }
}

RecyclerListViewFragment

public class RecyclerListViewFragment extends Fragment {
    private RecyclerView mRecyclerView;
    private RecyclerView.LayoutManager mLayoutManager;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.Adapter mWrappedAdapter;
    private RecyclerViewDragDropManager mRecyclerViewDragDropManager;
    private RecyclerViewSwipeManager mRecyclerViewSwipeManager;
    private RecyclerViewTouchActionGuardManager mRecyclerViewTouchActionGuardManager;

    public RecyclerListViewFragment() {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_recycler_list_view, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //noinspection ConstantConditions
        mRecyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view);
        mLayoutManager = new LinearLayoutManager(getContext());

        // touch guard manager  (this class is required to suppress scrolling while swipe-dismiss animation is running)
        mRecyclerViewTouchActionGuardManager = new RecyclerViewTouchActionGuardManager();
        mRecyclerViewTouchActionGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
        mRecyclerViewTouchActionGuardManager.setEnabled(true);

        // drag & drop manager
        mRecyclerViewDragDropManager = new RecyclerViewDragDropManager();
        mRecyclerViewDragDropManager.setDraggingItemShadowDrawable(
                (NinePatchDrawable) ContextCompat.getDrawable(getContext(), R.drawable.material_shadow_z3));

        // swipe manager
        mRecyclerViewSwipeManager = new RecyclerViewSwipeManager();

        //adapter
        final MyDraggableSwipeableItemAdapter myItemAdapter = new MyDraggableSwipeableItemAdapter(getDataProvider());
        myItemAdapter.setEventListener(new MyDraggableSwipeableItemAdapter.EventListener() {
            @Override
            public void onItemRemoved(int position) {
                ((DraggableSwipeableExampleActivity) getActivity()).onItemRemoved(position);
            }

            @Override
            public void onItemViewClicked(View v, boolean pinned) {
                onItemViewClick(v, pinned);
            }
        });

        mAdapter = myItemAdapter;

        mWrappedAdapter = mRecyclerViewDragDropManager.createWrappedAdapter(myItemAdapter);      // wrap for dragging
        mWrappedAdapter = mRecyclerViewSwipeManager.createWrappedAdapter(mWrappedAdapter);      // wrap for swiping

        final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
        animator.setSupportsChangeAnimations(false);

        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mWrappedAdapter);  // requires *wrapped* adapter
        mRecyclerView.setItemAnimator(animator);

        // additional decorations
        //noinspection StatementWithEmptyBody
        if (supportsViewElevation()) {
            // Lollipop or later has native drop shadow feature. ItemShadowDecorator is not required.
        } else {
            mRecyclerView.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) ContextCompat.getDrawable(getContext(), R.drawable.material_shadow_z1)));
        }
        mRecyclerView.addItemDecoration(new SimpleListDividerDecorator(ContextCompat.getDrawable(getContext(), R.drawable.list_divider_h), true));
        mRecyclerViewTouchActionGuardManager.attachRecyclerView(mRecyclerView);
        mRecyclerViewSwipeManager.attachRecyclerView(mRecyclerView);
        mRecyclerViewDragDropManager.attachRecyclerView(mRecyclerView);
    }

    @Override
    public void onPause() {
        mRecyclerViewDragDropManager.cancelDrag();
        super.onPause();
    }

    @Override
    public void onDestroyView() {
        if (mRecyclerViewDragDropManager != null) {
            mRecyclerViewDragDropManager.release();
            mRecyclerViewDragDropManager = null;
        }

        if (mRecyclerViewSwipeManager != null) {
            mRecyclerViewSwipeManager.release();
            mRecyclerViewSwipeManager = null;
        }

        if (mRecyclerViewTouchActionGuardManager != null) {
            mRecyclerViewTouchActionGuardManager.release();
            mRecyclerViewTouchActionGuardManager = null;
        }

        if (mRecyclerView != null) {
            mRecyclerView.setItemAnimator(null);
            mRecyclerView.setAdapter(null);
            mRecyclerView = null;
        }

        if (mWrappedAdapter != null) {
            WrapperAdapterUtils.releaseAll(mWrappedAdapter);
            mWrappedAdapter = null;
        }
        mAdapter = null;
        mLayoutManager = null;

        super.onDestroyView();
    }

    private void onItemViewClick(View v, boolean pinned) {
        int position = mRecyclerView.getChildAdapterPosition(v);
        if (position != RecyclerView.NO_POSITION) {
            ((DraggableSwipeableExampleActivity) getActivity()).onItemClicked(position);
        }
    }

    public AbstractDataProvider getDataProvider() {
        return ((DraggableSwipeableExampleActivity) getActivity()).getDataProvider();
    }

    public void notifyItemChanged(int position) {
        mAdapter.notifyItemChanged(position);
    }

    public void notifyItemInserted(int position) {
        mAdapter.notifyItemInserted(position);
        mRecyclerView.scrollToPosition(position);
    }
}

2 个答案:

答案 0 :(得分:3)

要从数据提供者类中的recyclerView更新onPostExecute,您的onPostExecute应该可以访问已定义context的{​​{1}}。

由于您在recyclerView类中定义了FetchExercise异步任务,请尝试将ExerciseDataProvider activity传递给context的构造函数,然后将其传递给{ {1}}异步任务,如下所述:getting context in AsyncTask

ExerciseDataProvider

使用FetchExercise更新public class MyCustomTask extends AsyncTask<Void, Void, Long> { private Context mContext; public MyCustomTask (Context context){ mContext = context; } protected void onPostExecute(Long result) { //use mContext to update recycler view } } }

<强>更新

第1步

定义context,该recyclerView将通知您interface内的数据集更改,该类会初始化您的activity并将data provider class传递给activity context的构造函数。

data provider class

第2步

public class ExampleDataProviderFragment extends Fragment { private AbstractDataProvider mDataProvider; //Define an interface that will notify your activity of data set change public interface EventListener { void onNotifyDataSetChanged(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); //Pass activity context to ExerciseDataProvider mDataProvider = new ExerciseDataProvider(getActivity()); } public AbstractDataProvider getDataProvider() { return mDataProvider; } } 参数添加到context的构造函数,并使用它来通知实现接口的活动以通知数据集更改。

ExerciseDataProvider

第3步

public class ExerciseDataProvider extends AbstractDataProvider { private List<ConcreteData> mData; private ConcreteData mLastRemovedData; private int mLastRemovedPosition = -1; //Add context parameter to constructor public ExerciseDataProvider(Context context) { //Pass context to async task new FetchExercise(context).execute(); mData = new LinkedList<>(); } class FetchExercise extends AsyncTask<Void,Void,Integer> { Context mContext; public FetchExercise(Context context) { mContext = context; } @Override protected Integer doInBackground(Void... params) { ... return 1; } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); //Typecast context to interface defined above //and notify dataset changes by calling its method ExampleDataProviderFragment.EventListener eventListener = (ExampleDataProviderFragment.EventListener)mContext; eventListener.onNotifyDataSetChanged(); } } } 中实施上面定义的interface,并在其中通知activity class recyclerview

adapter

答案 1 :(得分:0)

我认为@random是正确的,你应该在post post上通知你的Recycle视图。

@Override
protected void onPostExecute(Void aVoid) {
    mRecyclerViewAdapter.notifyDataSetChanged();
    super.onPostExecute(aVoid);
}

或者如果你在异步任务中做了一些事情来添加/删除数据集中的某些内容,你会这样做:

@Override
protected void onPostExecute(Void aVoid) {
    mRecyclerViewAdapter.notifyItemRemoved(itemposition); // or item added
    mRecyclerViewAdapter.notifyDataSetChanged();
    super.onPostExecute(aVoid);
}

希望它有所帮助!