其他分享
首页 > 其他分享> > android – 无法从我的模型类更新RecyclerView?

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

作者:互联网

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

数据正在一个名为ExerciseDataProvider&的类中被提取. RV代码是另一个Fragment 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();
    }

数据提供者

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

解决方法:

要从数据提供程序类中的onPostExecute更新recyclelerView,您的onPostExecute应该可以访问定义了recyclerView的上下文.

由于您的FetchExercise异步任务是在ExerciseDataProvider类中定义的,因此请尝试将活动上下文传递给ExerciseDataProvider的构造函数,然后将其传递给FetchExercise异步任务,如下所述:getting context in AsyncTask

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

使用上下文更新recyclerView.

UPDATE

步骤1

定义一个接口,该接口将在类中通知您的数据集更改活动,该类初始化数据提供程序类并将活动上下文传递给数据提供程序类的构造函数.

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

第2步

将上下文参数添加到ExerciseDataProvider的构造函数,并使用它来通知实现接口的活动以通知数据集更改.

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();

        }
    }
}

第3步

在您的活动类中实现上面定义的接口,并通知其中的recyclerview适配器

public class DraggableSwipeableExampleActivity extends AppCompatActivity 
    implements ExampleDataProviderFragment.EventListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
    }

    //implement interface method and notify recyclerview of changes
    @Override
    public void onNotifyDataSetChanged() {
        Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_LIST_VIEW);

        // you might need to change visibility of `mWrappedAdapter` in the fragment that defines it or create a getter for it so that you can access it here
        ((RecyclerListViewFragment) fragment).mWrappedAdapter.notifyDataSetChanged(); 

    }
 ...
}

标签:android,android-recyclerview,recycler-adapter,notifydatasetchanged
来源: https://codeday.me/bug/20190628/1312360.html