当前位置: 首页 > 知识库问答 >
问题:

获取RecyclerView以重新加载项目

李振国
2023-03-14

我目前正在开发一个应用程序,可以在用户手机上找到所有MP3,然后将它们放入列表中。这是非常好的工作,非常快,即使有很多歌曲。现在,我为列表中的每个项目填充一个新列表,然后将其显示在我的recyclerview中。问题是,我的手机上有700首歌曲,这在相当长的一段时间内会阻塞UI线程。

现在,我想使用回收站视图不将列表中的所有项目一次加载到对象中,而是仅在它们即将显示时加载-但我不知道如何做到这一点。现在,所有对象都被构建,然后在UI线程被阻塞30秒后在回收站视图中显示在一个很长的滚动视图中。有人能帮我吗?这是我的代码:

namespace Media_Player
{
    [Activity(Label = "Media_Player", MainLauncher = true)]
    public class MainActivity : Activity
    {
        static public MediaPlayer mediaPlayer;
        List<MP3object> mp3;
        MediaMetadataRetriever reader;
        public static Button btn_StartOrPause, btn_Stop;
        public static TextView txt_CurrentSong;
        public static bool stopIsActive = false, firstStart = true;
        public static Android.Net.Uri CurrentActiveSongUri;

        RecyclerView mRecyclerView;
        RecyclerView.LayoutManager mLayoutManager;
        PhotoAlbumAdapter mAdapter;


        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.test);

            reader = new MediaMetadataRetriever();
            PopulateMP3List(ReturnPlayableMp3(true));
            mediaPlayer = new MediaPlayer();

            InitRecView();
        }

        private void InitRecView()
        {

            // Instantiate the adapter and pass in its data source:
            mAdapter = new PhotoAlbumAdapter(mp3);

            // Get our RecyclerView layout:
            mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);

            // Plug the adapter into the RecyclerView:
            mRecyclerView.SetAdapter(mAdapter);

            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.SetLayoutManager(mLayoutManager);
        }


        private void PopulateMP3List(List<string> content)
        {
           mp3 = new List<MP3object>();        
           foreach (string obj in content)
           {
               WriteMetaDataToFileList(obj);        
           }
        }

        void WriteMetaDataToFileList(string obj)
        {
            reader.SetDataSource(obj);

            //Write Mp3 as object to global list
            MP3object ob = new MP3object();
            {
                if(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != null)
                {
                    ob.SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
                }
                else
                {
                    ob.SongName = Resources.GetString(Resource.String.Unknown);
                }

                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != null)
                {
                    ob.ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
                }
                else
                {
                    ob.ArtistName = Resources.GetString(Resource.String.Unknown);
                }

                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != null)
                {
                    ob.AlbumName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum);
                }
                else
                {
                    ob.AlbumName = Resources.GetString(Resource.String.Unknown);
                }

                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
                {
                    ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
                }
                else
                {
                    ob.Year = Resources.GetString(Resource.String.Unknown);
                }

                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
                {
                    ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
                }
                else
                {
                    ob.Year = Resources.GetString(Resource.String.Unknown);
                }

                ob.Mp3Uri = obj; // can never be unknown!

                ob.DurationInSec = int.Parse(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyDuration)) / 1000; // can never be unknown, div by 1000 to get sec not millis
            }
            mp3.Add(ob);

        }

        public List<string> ReturnPlayableMp3(bool sdCard)
        {
            List<string> res = new List<string>();
            string phyle;
            string path1 = null;

            if(sdCard) // get mp3 from SD card
            {
                string baseFolderPath = "";

                try
                {
                    bool getSDPath = true;

                    Context context = Application.Context;
                    Java.IO.File[] dirs = context.GetExternalFilesDirs(null);

                    foreach (Java.IO.File folder in dirs)
                    {
                        bool IsRemovable = Android.OS.Environment.InvokeIsExternalStorageRemovable(folder);
                        bool IsEmulated = Android.OS.Environment.InvokeIsExternalStorageEmulated(folder);

                        if (getSDPath ? IsRemovable && !IsEmulated : !IsRemovable && IsEmulated)
                            baseFolderPath = folder.Path;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("GetBaseFolderPath caused the following exception: {0}", ex);
                }

                string xy = baseFolderPath.Remove(18); // This is result after this, but this hard coded solution could be a problem on different phones.: "/storage/05B6-2226/Android/data/Media_Player.Media_Player/files"

                path1 = xy;
                // path to SD card and MUSIC "/storage/05B6-2226/"
            }
            else // get Mp3 from internal storage
            {
                    path1 = Android.OS.Environment.ExternalStorageDirectory.ToString();
            }

            var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);

            foreach (string currentFile in mp3Files)
            {
                phyle = currentFile;
                res.Add(phyle);
            }

            return res;
        }


    }

    public class PhotoViewHolder : RecyclerView.ViewHolder
    {
        public ImageView Image { get; private set; }
        public TextView Caption { get; private set; }

        public PhotoViewHolder(View itemView) : base(itemView)
        {
            // Locate and cache view references:
            Image = itemView.FindViewById<ImageView>(Resource.Id.imageView);
            Caption = itemView.FindViewById<TextView>(Resource.Id.textView);
        }
    }

    public class PhotoAlbumAdapter : RecyclerView.Adapter
    {
        public List<MP3object> mp3;
        public PhotoAlbumAdapter(List<MP3object> mp3)
        {
            this.mp3 = mp3;
        }

        public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
        {
            View itemView = LayoutInflater.From(parent.Context).
                        Inflate(Resource.Layout.lay, parent, false);
            PhotoViewHolder vh = new PhotoViewHolder(itemView);
            return vh;
        }

        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
        {
            PhotoViewHolder vh = holder as PhotoViewHolder;
            vh.Caption.Text = mp3[position].SongName;
        }

        public override int ItemCount
        {
            get { return mp3.Count(); }
        }
    }



}

因此,获取具有Mp3位置的字符串列表非常快,但随后“WriteMetaDataToFileList(obj)”开始,来自“PopulateMP3List(List内容)”,这就是需要很长时间的原因。我认为我需要的是让回收器视图只构建前20个对象,当用户开始滚动时,构建接下来的20个对象并将它们附加到列表中以使它们也可以滚动。请在这里帮助我:)

共有1个答案

盖斌
2023-03-14

下面是一个抽象类:

public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
private LinearLayoutManager linearLayoutManager;

protected PaginationScrollListener(LinearLayoutManager linearLayoutManager) {
    this.linearLayoutManager = linearLayoutManager;
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    int visibleItemCount = linearLayoutManager.getChildCount();
    int totalItemCount = linearLayoutManager.getItemCount();
    int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
    if (!isLoading() && !isLastPage()) {
        if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
            loadMoreItems();
        }
    }
}

protected abstract void loadMoreItems();

public abstract boolean isLastPage();

public abstract boolean isLoading();
}

在适配器中,必须遵循以下模式:

public class ConsultancyAdapter extends      RecyclerView.Adapter<ConsultancyAdapter.ConsultancyVH> {
private static final int ITEM = 0;
private static final int LOADING = 1;
private boolean isLoadingAdded = false;

public ConsultancyAdapter(List<Consultancy> consultancies, ConsultancyAdapterListener listener) {
}

@NonNull
@Override
public ConsultancyVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder viewHolder = null;
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    switch (viewType) {
        case ITEM:
            viewHolder = getViewHolder(parent, layoutInflater);
            break;
        case LOADING:
            View v2 = layoutInflater.inflate(R.layout.item_progress, parent, false);
            viewHolder = new ConsultancyVH(v2);
            break;
    }
    return (ConsultancyVH) viewHolder;
}
@NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
    RecyclerView.ViewHolder viewHolder;
    View v1 = inflater.inflate(R.layout.item_consultancy, parent, false);
    viewHolder = new ConsultancyVH(v1);
    return viewHolder;
}

@Override

public void onBindViewHolder(@NonNull ConsultancyVH holder, int position) {
    Consultancy consultancy = consultancies.get(position);
    switch (getItemViewType(position)) {
        case ITEM:
            ConsultancyVH mySingeCounseller = holder;
            holder.title.setText(consultancy.getTitle());  // set cardTitle
            holder.fieldArea.setText(consultancy.getField_filedoctorskills());               

            break;
        case LOADING:
            break;
    }
}    


@Override
public int getItemCount() {
    return consultancies.size();
}
@Override
public int getItemViewType(int position) {
    return (position == consultancies.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
}

public void add(Consultancy mc) {
    consultancies.add(mc);
    notifyItemInserted(consultancies.size() - 1);
}

public void addAll(List<Consultancy> mcList) {
    for (Consultancy mc : mcList) {
        add(mc);
    }
}

public void remove(Consultancy city) {
    int position = consultancies.indexOf(city);
    if (position > -1) {
        consultancies.remove(position);
        notifyItemRemoved(position);
    }
}

public Consultancy getItem(int position) {
    return consultancies.get(position);
}

public void clear() {
    isLoadingAdded = false;
    while (getItemCount() > 0) {
        remove(getItem(0));
    }
}

public boolean isEmpty() {
    return getItemCount() == 0;
}

public void addLoadingFooter() {
    isLoadingAdded = true;
    add(new Consultancy());
}

public void removeLoadingFooter() {
    isLoadingAdded = false;

    int position = consultancies.size() - 1;
    Consultancy item = getItem(position);


    if (item != null) {
        consultancies.remove(position);
        notifyItemRemoved(position);
    }
}

public interface ConsultancyAdapterListener {
    void onCaseClicked(int position, String nid, String fieldArea, String title);
}

protected class ConsultancyVH extends RecyclerView.ViewHolder {
    private TextView title, fieldArea;
    private CircleImageView iconProfile;
    private MaterialRippleLayout caseButtonRipple;

    public ConsultancyVH(View itemView) {
        super(itemView);
        caseButtonRipple = itemView.findViewById(R.id.case_button_ripple);
        this.title = itemView.findViewById(R.id.docName);
        this.fieldArea = itemView.findViewById(R.id.fieldArea);
        this.iconProfile = itemView.findViewById(R.id.icon_profile);
    }

}
}

在你的活动中:

    private void setScrollListener() {
    recyclerView.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
        @Override
        protected void loadMoreItems() {
            isLoading = true;
            currentPage += 1;
                    loadNextPage();
        }

        @Override
        public boolean isLastPage() {
            return isLastPage;
        }

        @Override
        public boolean isLoading() {
            return isLoading;
        }
    });
                    loadFirstPage();

}

在我的loadFirstPage中,我与API对话,您需要一些代码:

private void loadFirstPage() {
    CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
        @Override
        protected void onFailure(Throwable t) {
            super.onFailure(t);
        }

        @Override
        protected void onSuccess(List<Consultancy> response) {
            swipeRefreshLayout.setRefreshing(false);
            dataList = response;
            adapter.addAll(dataList);
            recyclerView.setAdapter(adapter);
            if (!checkLast(response)) adapter.addLoadingFooter();
            else isLastPage = true;
        }

        @Override
        protected void onOtherStatus(Response<List<Consultancy>> response) {
            super.onOtherStatus(response);
        }

        @Override
        protected void always() {
            super.always();
        }
    });
}

并加载下一页:

private void loadNextPage() {
    CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
        @Override
        protected void onFailure(Throwable t) {
            super.onFailure(t);
        }

        @Override
        protected void onSuccess(List<Consultancy> response) {
            swipeRefreshLayout.setRefreshing(false);
            adapter.removeLoadingFooter();
            isLoading = false;
            swipeRefreshLayout.setRefreshing(false);
            adapter.addAll(response);
            if (!checkLast(response)) adapter.addLoadingFooter();
            else isLastPage = true;
        }

        @Override
        protected void onOtherStatus(Response<List<Consultancy>> response) {
            super.onOtherStatus(response);
        }

        @Override
        protected void always() {
            super.always();
        }
    });
}
 类似资料:
  • 是否可以在Java中获取重新加载的url? 我需要检索令牌附加到url后加载下面的超文本标记语言页面。 最初,URL将为 http://localhost:8080/validate.html?invisible=true代码 成功后它将是 <代码>http://localhost:8080/validate.html?token=xyz 我需要在Java中检索令牌值。 我尝试了下面的代码,但va

  • 正如在C 11中所知,有6个内存顺序,在关于std::memory\u order\u acquire的文档中: http://en.cppreference.com/w/cpp/atomic/memory_order memory\u order\u acquire内存\u顺序\u获取 具有此内存顺序的加载操作对受影响的内存位置执行获取操作:在此加载之前,当前线程中的内存访问不能重新排序。这可以

  • 我还在想办法弄清楚回收站。我有一个arraylist,用于初始化回收器视图。 如何在设置适配器和布局管理器后向回收器视图添加新项目? 所以基本上,在我和之后,我如何向RecyclerView添加一个新项目呢??

  • 我在Hibernate重新加载查询中的实体时遇到问题,即使它们是作为主查询的一部分获取的。 实体如下(简化) 这是对父/子关系的闭包表进行建模。 我制定了以下一些标准 这导致以下SQL查询 看起来它正确地实现了连接获取。但是当我执行 我在结果集中的每行SQL日志中看到这些条目之一 看起来即使DataContents被标记为懒加载,它也在急切地加载。 因此,我要么希望在我的查询中以某种方式获取加入数

  • 如何在中获取当前项?在我的用例中,RV项占用了所有屏幕空间,因此一次只有一个项。我以前试过谷歌,但没有找到任何有用的东西。

  • 本文向大家介绍RecyclerView下拉刷新上拉加载,包括了RecyclerView下拉刷新上拉加载的使用技巧和注意事项,需要的朋友参考一下 一 、前言 最近实在太忙,一个多礼拜没有更新文章了,于是今晚加班加点把demo写出来,现在都12点了才开始写文章。 1.我们的目标 把RecyclerView下拉刷新上拉加载更多加入到我们的开发者头条APP中。 2.效果图 3.实现步骤 找一个带上拉刷新下