【问题标题】:How to use ParseObjects with a RecyclerView?如何将 ParseObjects 与 RecyclerView 一起使用?
【发布时间】:2018-01-22 13:36:34
【问题描述】:

我正在尝试从我的解析服务器中提取数据并在 CardViews 的 RecyclerView 中显示图像和文本。我遇到了一些问题,其中一些可能没有得到适当的更正,所以请随时更正您在我当前的两个问题之外找到的任何新手代码。最后我的两个问题是。

  1. 数据最初不显示。我在 ViewPager 中有 3 个选项卡,我必须滑动两次才能显示。如果我在选项卡 1 上,则数据不会出现,直到我滑动到选项卡 3 并返回到选项卡 1,反之亦然。因为没有标签 4,所以标签 2 永远不会显示。

  2. 我目前面临的第二个问题是有时数据不匹配。它将使一行中的图片与另一个实体的描述相匹配。

下面是我的 MusicFragment.java

public class MusicFragment extends Fragment {

    private ArrayList<String> titles = new ArrayList<>();
    private ArrayList<Bitmap> bitmaps = new ArrayList<>();
    private ArrayList<String> descriptions = new ArrayList<>();

    private boolean notComplete = true;

    public MusicFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //  Inflate the layout for this fragment
        RecyclerView musicRecycler = (RecyclerView)inflater.inflate(
                            R.layout.fragment_music, container, false);

        if (notComplete) {
            //  Get the MusicFragImages class as a reference.
            ParseQuery<ParseObject> query = new ParseQuery<>("MusicFragImages");

            query.findInBackground(new FindCallback<ParseObject>() {
                @Override
                public void done(List<ParseObject> objects, ParseException e) {

                    if (e == null) {
                        for (ParseObject object : objects) {
                            String description = (String) object.get("description");
                            ParseFile file = (ParseFile) object.get("image");
                            String title = (String) object.get("title");

                            titles.add(title);
                            descriptions.add(description);

                            file.getDataInBackground(new GetDataCallback() {
                                @Override
                                public void done(byte[] data, ParseException e) {
                                    if (e == null && data != null) {
                                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                                        bitmaps.add(bitmap);
                                    }
                                }
                            });
                        }
                    } else {
                        Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                }

            });
            notComplete = false;
        }
        //  Create captioned images and registers it to the adapter.
        CaptionedImagesAdapter adapter = new CaptionedImagesAdapter(titles, bitmaps, descriptions);
        musicRecycler.setAdapter(adapter);

        //  Set up the layout.
        GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
        musicRecycler.setLayoutManager(layoutManager);

        adapter.setListener(new CaptionedImagesAdapter.Listener() {
           public void onClick(int position) {
               Intent intent;
               switch (position) {
                   case 0:
                       intent = new Intent(getActivity(), AudioActivity.class);
                       getActivity().startActivity(intent);
                       break;
                   case 1:
                       intent = new Intent(getActivity(), VideoActivity.class);
                       getActivity().startActivity(intent);
                       break;
               }
           }
        });

        return musicRecycler;
    }
}

另外,这是我的 CaptionedImagesAdapter

class CaptionedImagesAdapter extends
    RecyclerView.Adapter<CaptionedImagesAdapter.ViewHolder> {

    private final ArrayList<String> captions;
    private final ArrayList<Bitmap> bitmaps;
    private final ArrayList<String> descriptions;

    private Listener listener;

    interface Listener {
        void onClick(int position);
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        private final CardView cardView;

        public ViewHolder(CardView v) {
            super(v);
            cardView = v;
        }
    }

    public CaptionedImagesAdapter(ArrayList<String> captions, ArrayList<Bitmap> bitmaps, ArrayList<String> descriptions) {
        this.captions = captions;
        this.bitmaps = bitmaps;
        this.descriptions = descriptions;
    }

    @Override
    public int getItemCount() {
        return captions.size();
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }
    @Override
    public CaptionedImagesAdapter.ViewHolder onCreateViewHolder(
            ViewGroup parent, int viewType) {
        CardView cv = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_selection_2, parent, false);
        return new ViewHolder(cv);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final int index = position;

        //  Creates a CardView
        CardView cardView = holder.cardView;

        ImageView imageView = cardView.findViewById(R.id.type_image);
        imageView.setImageBitmap(bitmaps.get(index));

        imageView.setContentDescription(descriptions.get(index));

        //  Populate the caption.
        TextView textView = cardView.findViewById(R.id.type_text);
        textView.setText(captions.get(index));
        cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                if (listener != null)
                    listener.onClick(index);
            }
        });
    }
}

供参考......如果需要 MainActivity.java 在下面

    public class MainActivity extends AppCompatActivity {

//  Variables for the audio player.
public static MediaPlayer mediaPlayer;
public static int albumId;
public static int currentSong = -1;
public static boolean isPlaying = false;
private static int[] songs;

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

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

    //  Attach the SectionsPageAdapter to the ViewPager
    SectionsPageAdapter pagerAdapter = new SectionsPageAdapter(getSupportFragmentManager());
    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(pagerAdapter);
    int currentTab = 0;
    pager.setCurrentItem(currentTab);

    //  Attach the ViewPager to the TabLayout
    TabLayout tabLayout = (TabLayout)findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(pager);

    //  Starts the player.
    player();
}
public boolean onCreateOptionsMenu(Menu menu) {
    //  Inflate the menu; this adds items to the app bar.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Intent intent;
    switch (item.getItemId()) {
        case R.id.action_contact:
            intent = new Intent(MainActivity.this, ContactActivity.class);
            startActivity(intent);
            return true;
        case R.id.action_cart:
            intent = new Intent(this, CartActivity.class);
            startActivity(intent);
            return true;
        case R.id.action_member:
            intent = new Intent(this, ProfileActivity.class);
            startActivity(intent);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
private class SectionsPageAdapter extends FragmentPagerAdapter {

    public SectionsPageAdapter(FragmentManager fm) {
        super(fm);
    }
    @Override
    public int getCount() {
        return 3;
    }
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new MusicFragment();
            case 1:
                return new ArtFragment();
            case 2:
                return new FashionFragment();
        }
        return null;
    }
    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return getResources().getText(R.string.title_music);
            case 1:
                return getResources().getText(R.string.title_art);
            case 2:
                return getResources().getText(R.string.title_fashion);
        }
        return null;
    }
}
private void player() {

    /*Create a background thread that will automatically advance to
                * the next song, as long as there is a next song.*/

    //  Get the songs.
    songs = AudioData.audio[albumId].getSongs();

    final Handler handler = new Handler();
    handler.post(new Runnable() {
        @Override
        public void run() {
            if (isPlaying) {
                if (!(mediaPlayer.isPlaying()) && currentSong < songs.length - 1) {
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                    currentSong++;
                    mediaPlayer = MediaPlayer.create(MainActivity.this, songs[currentSong]);
                    mediaPlayer.start();
                    isPlaying = true;
                }
                //Set the flag to false at the end of the album.
                if (currentSong == songs.length) {
                    isPlaying = false;
                }
            }
            handler.postDelayed(this, 1000);
        }
    });
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    finishAffinity();
}

}

再次感谢 Harikumar 纠正第一个问题。我最终用下面的代码纠正了第二个问题。它在增强 for 循环中。

    for (ParseObject object : objects) {
                        String description = (String) object.get("description");
                        ParseFile file = (ParseFile) object.get("image");
                        String title = (String) object.get("title");
                        Bitmap bitmap;


                        titles.add(title);
                        descriptions.add(description);

                        byte[] data;
                        try {
                            data = file.getData();
                            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                            bitmaps.add(bitmap);
                            adapter.notifyDataSetChanged(); //notify your adapter that data has changed
                        } catch (ParseException pe) {
                            Toast.makeText(getContext(), pe.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }

【问题讨论】:

  • viewpager 使用的是哪个适配器?
  • 我正在使用 SectionsPageAdapter。我已将 MainActivity 代码添加到顶部以供参考。
  • 理想情况下,您应该为将(caption, description, bitmap) 作为一个单元保存的适配器创建一个对象,而不是使用三个并行列表,然后您可以拥有一个CaptionedImagesAdapter(List&lt;CaptionedImage&gt; images)

标签: java android android-recyclerview android-adapter bitnami


【解决方案1】:

如果您通知适配器CaptionedImagesAdapter,数据将会更新。尝试将代码修改为:

public class MusicFragment extends Fragment {

    private ArrayList<String> titles = new ArrayList<>();
    private ArrayList<Bitmap> bitmaps = new ArrayList<>();
    private ArrayList<String> descriptions = new ArrayList<>();
    private CaptionedImagesAdapter adapter;


    private boolean notComplete = true;

    public MusicFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //  Inflate the layout for this fragment
        RecyclerView musicRecycler = (RecyclerView)inflater.inflate(
                            R.layout.fragment_music, container, false);


        GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
        musicRecycler.setLayoutManager(layoutManager);

        adapter = new CaptionedImagesAdapter(titles, bitmaps, descriptions);

        musicRecycler.setAdapter(adapter);

        if (notComplete) {
            //  Get the MusicFragImages class as a reference.
            ParseQuery<ParseObject> query = new ParseQuery<>("MusicFragImages");

            query.findInBackground(new FindCallback<ParseObject>() {
                @Override
                public void done(List<ParseObject> objects, ParseException e) {

                    if (e == null) {
                        for (ParseObject object : objects) {
                            String description = (String) object.get("description");
                            ParseFile file = (ParseFile) object.get("image");
                            String title = (String) object.get("title");

                            titles.add(title);
                            descriptions.add(description);

                            file.getDataInBackground(new GetDataCallback() {
                                @Override
                                public void done(byte[] data, ParseException e) {
                                    if (e == null && data != null) {
                                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                                        bitmaps.add(bitmap);
                                        adapter.notifyDataSetChanged(); //notify your adapter that data has changed
                                    }
                                }
                            });
                        }
                    } else {
                        Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                }

            });
            notComplete = false;
        }


        adapter.setListener(new CaptionedImagesAdapter.Listener() {
           public void onClick(int position) {
               Intent intent;
               switch (position) {
                   case 0:
                       intent = new Intent(getActivity(), AudioActivity.class);
                       getActivity().startActivity(intent);
                       break;
                   case 1:
                       intent = new Intent(getActivity(), VideoActivity.class);
                       getActivity().startActivity(intent);
                       break;
               }
           }
        });

        return musicRecycler;
    }
}

这是您的第二个解决方案的一个小优化:在 for 循环之后仅更新一次 notifyDataSetChanged()(将其放在 for 循环之外)。这在性能方面更好。

【讨论】:

  • 谢谢!这解决了我的第一个问题。我仍在努力解决第二个问题。
  • 嗨,哈里库玛!非常感谢您的帮助。我解决了第二个问题。如果您愿意,请参阅上面的详细信息。
  • 我已经编辑了我的答案,并为您的第二期添加了优化。如果此答案有助于解决您的问题,请点赞并将其标记为答案,因为这将对遇到相同问题的其他人有所帮助。快乐编码:)
  • 我很想这样做,但是我是新手,没有 15 岁的声望让我能够这样做。
猜你喜欢
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 2019-01-25
相关资源
最近更新 更多