【问题标题】:Xamarin - Listview image cell images disappear on scrollingXamarin - Listview 图像单元格图像在滚动时消失
【发布时间】:2017-05-05 09:55:44
【问题描述】:

我正在我的 Xamarin android 应用程序中使用 ImageCell 显示所有电话簿联系人的列表。

列表显示联系人图片、联系人姓名和联系人号码。所有信息都正确显示,但当我向下滚动时,所有联系人图像都会消失并且永远不会重新加载,除非并且直到我重新运行应用程序。

下面是获取所有联系人的代码:

var contactList = new List < ContactsModel > ();

var ContactDetailURI = ContactsContract.Contacts.ContentUri;

string[] ContactDetailProjection = {
    ContactsContract.Contacts.InterfaceConsts.DisplayName,
    ContactsContract.Contacts.InterfaceConsts.PhotoId,
    //ContactsContract.Contacts.InterfaceConsts.PhotoThumbnailUri
};

var ContactDetailCursor = Forms.Context.ContentResolver.Query(ContactDetailURI, ContactDetailProjection, null, null, null);

if (ContactDetailCursor.MoveToFirst()) {
    do {
        var imageURI = Android.Net.Uri.Parse(new System.Uri(ContactDetailCursor.GetString(ContactDetailCursor.GetColumnIndex(ContactDetailProjection[1]))).ToString());
        var stream = Android.App.Application.Context.ContentResolver.OpenInputStream(imageURI);
        var imageSource = Xamarin.Forms.ImageSource.FromStream(() => stream);

        var contact = new ContactsModel();
        contact.DisplayName = ContactDetailCursor.GetString(ContactDetailCursor.GetColumnIndex(ContactDetailProjection[0]));
        contact.PhotoId = imageSource;

        contactList.Add(contact);

    } while (ContactDetailCursor.MoveToNext());
}

return contactList;

下面是显示所有联系人的页面的 XAML 代码:

<ContentPage.Content>
    <ListView x:Name="ContactList">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ImageCell
                    Text="{Binding DisplayName}"
                    Detail="{Binding PhoneNumber}"
                    ImageSource="{Binding PhotoId}">
                </ImageCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage.Content>

附:我没有使用任何类型的 pf 组件或包。

【问题讨论】:

  • 听起来流永远不会关闭...Android会回收视图,因此在滚动后图像不会显示,并且流仅在您关闭应用程序后才会关闭,因此在您重新运行时它可以工作它。您是否尝试过将流部分包装到 using 语句中?
  • 也许你是对的。你能指导我在哪里关闭流或包装流部分吗?我想我应该在 IF 语句结束标记之后编码关闭流部分。对吧?
  • 注意,“流”总是由 ImageSource.FromStream 方法处理的。如果 ImageSource 被同一图像的回收器视图调用两次,则可能您的流之前已发布...

标签: android xamarin xamarin.android xamarin.forms android-contacts


【解决方案1】:

我遇到了同样的问题。为了解决这个问题,我必须将 Stream 转换为字节数组,然后从新的字节数组转换回流。

这是我的代码

Stream stream = Android.App.Application.Context.ContentResolver.OpenInputStream(PhotoUri);
byte[] imageBytes = ReadFully(stream);
contact.Photo = Xamarin.Forms.ImageSource.FromStream(() => new MemoryStream(imageBytes));

public static byte[] ReadFully(Stream input)
    {
        byte[] buffer = new byte[16 * 1024];
        using (MemoryStream ms = new MemoryStream())
        {
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            return ms.ToArray();
        }
    }

您可以在此问题中阅读有关从流中创建字节数组的更多信息 Creating a byte array from a stream

【讨论】:

  • 谢谢,这就像一个魅力。但我仍然在问为什么图像会消失。
  • @Giuseppe 问题是当列表项从视图中消失时,Xamarin 将处理与其关联的所有流。但是当我们将它写入字节数组时,字节会留在内存中,并且每次都会释放流,但也会从这个数组中重新创建。 (对不起我的英语)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多