AndroidX 迁移后,ListView 未在 OnCreate/OnStart 上显示任何数据

Posted

技术标签:

【中文标题】AndroidX 迁移后,ListView 未在 OnCreate/OnStart 上显示任何数据【英文标题】:A ListView is not displaying any data on OnCreate/OnStart after AndroidX migration 【发布时间】:2021-07-17 21:11:18 【问题描述】:

我有一个应用程序,它只显示数据,直到我在 SearchView 上过滤某些内容。现在,在以下示例中,我在 Home Activity 和 More Sites Activity(发生错误的地方)之间切换。

正如您所看到的,当我切换到“更多站点”活动时,它唯一的 ListView 一直是空的,直到我“过滤”了一些东西。重要的是要强调,在我将应用程序迁移到 androidX 之前,More Sites Activity 可以正常工作。

这是我当前代码的一部分:

other_ruins.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:orientation="vertical">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_weight="1"
        android:layout_
        android:layout_>
        <LinearLayout
            android:layout_
            android:layout_
            android:orientation="vertical">
           <include layout="@layout/search_container" />
            <ListView
                android:id="@+id/lstOtherRuins"
                android:layout_margin="8dp"
                android:layout_
                android:layout_
                android:choiceMode="singleChoice"
                android:layout_gravity="left|start" />
        </LinearLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    <com.google.android.gms.ads.AdView
        android:id="@+id/adView"
        android:layout_
        android:layout_
        app:adSize="SMART_BANNER"
        app:adUnitId="@string/banner_ad_unit_id" />
</LinearLayout>

search_container.xml

<?xml version="1.0" encoding="UTF-8" ?>
<FrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar_container"
    android:layout_
    android:layout_>

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        app:theme="@style/ToolBarStyle"
        android:layout_
        android:layout_
        android:background="@color/colorPrimary" />

    <com.miguelcatalan.materialsearchview.MaterialSearchView
        android:id="@+id/search_view"
        android:layout_
        android:layout_ />
</FrameLayout>

这是我的 C# 代码,在这两种情况下,我都使用UpdateListView 方法:

protected override void OnStart()

    base.OnStart();

    UpdateListView(AllRuins);


private void UpdateListView(List<Row> result)

    List<IMenuItemsType> item = new();

    string prevCountry = "";

    foreach (var datum in result)
    
        if (datum.Col3 != prevCountry)
        
            prevCountry = datum.Col3;
            item.Add(new MenuHeaderItem(prevCountry));
        

        item.Add(new MenuContentSimpleItem(datum.Col1, datum.Col2, datum.Col3, datum.Col4, datum.Col5));
    

    LstOtherRuins.Adapter = new OtherRuinsAdapter(this, item);

这是 SearchView 过滤器:

public partial class OtherRuinsActivity

    public class MaterialSearchViewListener : Java.Lang.Object, MaterialSearchView.IOnQueryTextListener
    
        private readonly OtherRuinsActivity OActivity;

        public MaterialSearchViewListener(OtherRuinsActivity oActivity)
        
            OActivity = oActivity;
        

        public bool OnQueryTextChange(string p0)
        
            OActivity.CurrentWord = p0;
            OActivity.UpdateListView(OActivity.AllRuins.Where(x => x.Col1.ToLower().Contains(p0)).ToList());

            return true;
        

        public bool OnQueryTextSubmit(string p0)
        
            OActivity.CurrentWord = p0;
            OActivity.UpdateListView(OActivity.AllRuins.Where(x => x.Col1.ToLower().Contains(p0)).ToList());

            return true;
        
    

我已经验证并有数据:

这也是我的适配器:

public partial class OtherRuinsAdapter

    private class OtherRuinsViewHolder : Java.Lang.Object
    
        public TextView LblName  get; set; 
        public TextView LblLocation  get; set; 
    


public partial class OtherRuinsAdapter : ArrayAdapter<IMenuItemsType>

    public OtherRuinsAdapter(Context context, List<IMenuItemsType> items) : base(context, 0, items)
    
        Context1 = context;
        Items = items;
        Inflater = (LayoutInflater)Context1.GetSystemService(Context.LayoutInflaterService);
    

    public override int Count
    
        get
        
            return Items.Count;
        
    

    public Context Context1  get; set; 
    public List<IMenuItemsType> Items  get; set; 
    public LayoutInflater Inflater  get; set; 
    public LayoutInflater Inflater1  get => Inflater; set => Inflater = value; 

    public override long GetItemId(int position)
    
        return position;
    

    public override View GetView(int position, View convertView, ViewGroup parent)
    
        var inflater = LayoutInflater.From(parent.Context);
        OtherRuinsViewHolder holder = null;
        var view = convertView;

        if (view != null)
        
            holder = view.Tag as OtherRuinsViewHolder;
        

        if (holder == null)
        
            holder = new OtherRuinsViewHolder();
            view = inflater.Inflate(Resource.Layout.other_ruins_list, parent, false);
            holder.LblName = view.FindViewById<TextView>(Resource.Id.lblName);
            holder.LblLocation = view.FindViewById<TextView>(Resource.Id.lblLocation);
            view.Tag = holder;
        

        IMenuItemsType item = Items[position];
        if (item.GetMenuItemsType() == 0)
        
            MenuHeaderItem _headerItem = (MenuHeaderItem)item;
            view = inflater.Inflate(Resource.Layout.listview_header_item, null);
            // user dont click header item
            view.Clickable = false;

            var headerName = view.FindViewById<TextView>(Resource.Id.txtHeader);
            headerName.Text = _headerItem.HeaderText;

        
        else if (item.GetMenuItemsType() == 1)
        
            MenuContentSimpleItem _contentItem = (MenuContentSimpleItem)item;

            if (!string.IsNullOrEmpty(_contentItem.Wiki))
            
                holder.LblName.PaintFlags = PaintFlags.UnderlineText;
                holder.LblName.SetTextColor(Color.Argb(255, 10, 150, 124));
                holder.LblName.Click += LblName_Click;
            
            else
            
                holder.LblName.PaintFlags = PaintFlags.AntiAlias;
                holder.LblName.SetTextColor(Color.Argb(255, 33, 33, 33));
                holder.LblName.Click -= LblName_Click;
            

            if (!string.IsNullOrEmpty(_contentItem.SubScript))
            
                if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
                    holder.LblName.SetText(html.FromHtml($"_contentItem.Title<sub><small>_contentItem.SubScript</small></sub>", FromHtmlOptions.ModeLegacy), BufferType.Spannable);
                else
#pragma warning disable CS0618 // Type or member is obsolete
                    holder.LblName.SetText(Html.FromHtml($"_contentItem.Title<sub><small>_contentItem.SubScript</small></sub>"), BufferType.Spannable);
#pragma warning restore CS0618 // Type or member is obsolete
            
            else
            
                holder.LblName.Text = _contentItem.Title;
            

            holder.LblLocation.Text = _contentItem.Description;
            holder.LblLocation.PaintFlags = PaintFlags.UnderlineText;
            holder.LblLocation.Click += LblLocation_Click;
        

        return view;
    

    private void LblName_Click(object sender, System.EventArgs e)
    
        Context1.StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse(new XML2CSharp("OtherRuins.xml").FromXml<Book>().Row.Where(x => x.Col1 == ((TextView)sender).Text).FirstOrDefault().Col4)));
    

    private void LblLocation_Click(object sender, System.EventArgs e)
    
        Intent mapIntent = new Intent(Intent.ActionView, Android.Net.Uri.Parse($"google.navigation:q=((TextView)sender).Text, new XML2CSharp("OtherRuins.xml").FromXml<Book>().Row.Where(x => x.Col2 == ((TextView)sender).Text).FirstOrDefault().Col3"));
        mapIntent.SetPackage("com.google.android.apps.maps");
        Context1.StartActivity(mapIntent);
    

附:

似乎因为这个布局,GetView 没有被调用:

<LinearLayout
    android:layout_
    android:layout_
    android:orientation="vertical">
   <include layout="@layout/search_container" />
    <ListView
        android:id="@+id/lstOtherRuins"
        android:layout_margin="8dp"
        android:layout_
        android:layout_
        android:choiceMode="singleChoice"
        android:layout_gravity="left|start" />
</LinearLayout>

如果我删除LinearLayout,那么它可以工作,但会产生一个新错误:

A ListView overlaps a SearchView in a CoordinatorLayout

【问题讨论】:

对不起,我对你的应用程序的逻辑有点困惑。根据上面的视频,有两个列表,一个页面是纯文本列表,另一个是图片列表。它们之间是什么关系?以及在OnCreate/OnStart 后没有显示哪一页数据?你能详细说明一下吗? 另外,上面的代码属于哪个页面?如果方便的话,可以发一个基本的demo到github或者onedriver,方便我们测试一下吗? 嗨@JessieZhang-MSFT,似乎没有在事件中调用GetView,正如我在另一个问题***.com/questions/67252282/… 中解释的那样,因为它已加载,但还有另一个错误。 【参考方案1】:

由于包含ListViewLinerLayout,不知何故未调用GetView 方法。我重新编写了布局,现在它可以正常工作了。

other_ruins.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:orientation="vertical">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_weight="1"
        android:layout_
        android:layout_>
        <include layout="@layout/search_container" />
        <ListView
            android:id="@+id/lstOtherRuins"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:nestedScrollingEnabled="true"
            android:layout_margin="8dp"
            android:layout_
            android:layout_
            android:choiceMode="singleChoice"
            android:layout_below="@id/toolbar_container"
            android:layout_gravity="left|start" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    <com.google.android.gms.ads.AdView
        android:id="@+id/adView"
        android:layout_
        android:layout_
        app:adSize="SMART_BANNER"
        app:adUnitId="@string/banner_ad_unit_id" />
</LinearLayout>

另外,我需要通过添加 AppBarLayout 来更改容器,因为它被重叠了。

search_container.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<com.google.android.material.appbar.AppBarLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar_container"
    android:layout_
    android:layout_>

    <FrameLayout
        android:layout_
        android:layout_>

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            app:theme="@style/ToolBarStyle"
            android:layout_
            android:layout_
            android:background="@color/colorPrimary" />

        <com.miguelcatalan.materialsearchview.MaterialSearchView
            android:id="@+id/search_view"
            android:layout_
            android:layout_ />
    </FrameLayout>

</com.google.android.material.appbar.AppBarLayout>

【讨论】:

恭喜,请接受您的回答,以便对有类似主题的其他人有所帮助。提前致谢。 嗨@JessieZhang-MSFT,我接受了自己的答案。我仍然想知道为什么没有触发 GetView,因为我看不到这种关系,老实说,我是偶然发现的。

以上是关于AndroidX 迁移后,ListView 未在 OnCreate/OnStart 上显示任何数据的主要内容,如果未能解决你的问题,请参考以下文章

迁移到 AndroidX 后,findFragmentById 为片段返回 null

迁移到 Androidx 后无法解析符号 R

ListView 与 CoordinatorLayout 中的 SearchView 重叠

迁移到 AndroidX 后,RecyclerView 可过滤的 performFiltering() 不起作用

无法解析 android.support.design。迁移到 AndroidX 后

在 Android Studio 中迁移到 AndroidX 后出现 YoutubeAndroidPlayerAPI 错误