这就是我正在做的事情:
我将占位符图片设置为我的ViewCell的子类Image。
然后,从磁盘加载图片到替换占位符。
这适用于占位符,但是,从磁盘设置图像(正确显示)后,如果我滚出视图然后返回我得到了这个错误:
Cannot access a disposed object.
Object name: 'Stream has been closed'.
StackTrace:
at System.IO.FileStream.Read (System.Byte[] array, System.Int32 offset, System.Int32 count) [0x0000d] in <d18287e1d683419a8ec3216fd78947b9>:0
at Android.Runtime.InputStreamAdapter.Read (System.Byte[] bytes, System.Int32 offset, System.Int32 length) [0x00006] in <33e6e739ac344166b157e323586f11a1>:0
at Java.IO.InputStream.n_Read_arrayBII (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_b, System.Int32 off, System.Int32 len) [0x00019] in <33e6e739ac344166b157e323586f11a1>:0
at (wrapper dynamic-method) System.Object:c31b04e7-d4e0-4108-9aaf-784714d6a934 (intptr,intptr,intptr,int,int)
我的ViewModel:
ImageSource profilePhoto = ImageSource.FromFile(FileNames.ProfilePlaceholderPNG);
public ImageSource ProfilePhoto
{
get { return profilePhoto; }
set { profilePhoto = value; OnPropertyChanged(); }
}
public async Task LoadProfilePhoto()
{
// Set placeholder first
ProfilePhoto = ImageSource.FromFile(FileNames.ProfilePlaceholderPNG);
// Attemp to load existing photo
var photo = await Storage.Current.GetPhoto(FileNames.ProfilePictureJPG);
if (photo != null)
{
ProfilePhoto = photo;
}
}
Page.xaml.cs
private async Task SetTableView()
{
var profileCell = new UserProfileCell();
profileCell.Photo.BindingContext = viewModel;
profileCell.Photo.SetBinding(Image.SourceProperty, new Binding("ProfilePhoto", BindingMode.OneWay));
var tableSections = new List<TableSection>();
tableSections.Add(new TableSection()
{
profileCell
});
Content = new TableView
{
HasUnevenRows = true,
Intent = TableIntent.Menu,
Root = new TableRoot()
{
tableSections
}
};
await viewModel.LoadProfilePhoto();
}
从磁盘读取照片的代码:
public async Task<ImageSource> GetPhoto(string fileName)
{
var localStorage = FileSystem.Current.LocalStorage;
var folderExists = await localStorage.CheckExistsAsync(PhotosFolder);
if (!folderExists.Equals(ExistenceCheckResult.FolderExists))
return null;
var localStorageFolder = await localStorage.GetFolderAsync(PhotosFolder);
var fileExists = await localStorageFolder.CheckExistsAsync(fileName);
if (!fileExists.Equals(ExistenceCheckResult.FileExists))
return null;
IFile file = await localStorageFolder.GetFileAsync(fileName);
if (file == null)
return null;
var stream = await file.OpenAsync(FileAccess.Read);
var imageSource = ImageSource.FromStream(() => stream);
return imageSource;
}
现在它只发生在Android中。我在iOS上遇到了这个问题,但在使用占位符后问题就消失了。
现在仅在Android 中发生。我正在使用Xamarin.Forms。
我在这里做错了什么?
由于
答案 0 :(得分:0)
根据我能够收集到的信息, Xamarin将尝试处理不再使用的流。
为了解决这个问题,建议here
我将上述代码从 GetPhoto 修改为 GetPhotoBytes :
public async Task<byte[]> GetPhotoBytes(string fileName)
{
var localStorage = FileSystem.Current.LocalStorage;
var folderExists = await localStorage.CheckExistsAsync(PhotosFolder);
if (!folderExists.Equals(ExistenceCheckResult.FolderExists))
{
return null;
}
var localStorageFolder = await localStorage.GetFolderAsync(PhotosFolder);
var fileExists = await localStorageFolder.CheckExistsAsync(fileName);
if (!fileExists.Equals(ExistenceCheckResult.FileExists))
{
return null;
}
IFile file = await localStorageFolder.GetFileAsync(fileName);
if (file == null)
{
return null;
}
var stream = await file.OpenAsync(FileAccess.Read);
byte[] bytes = null;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
stream.Dispose();
bytes = memoryStream.ToArray();
}
return bytes;
}
现在,LoadProfilePhoto构建了一个来自字节的流:
public async Task LoadProfilePhoto()
{
// Set placeholder first
ProfilePhoto = ImageSource.FromFile(FileNames.ProfilePlaceholderPNG);
// Attemp to load existing photo
var photoBytes = await Storage.Current.GetPhotoBytes(FileNames.ProfilePictureJPG);
if (photoBytes != null)
{
var photo = ImageSource.FromStream(() => new System.IO.MemoryStream(photoBytes));
if (photo != null)
{
ProfilePhoto = photo;
}
}
}
现在不是使用文件中的流,而是从Photo字节创建一个新的。我还没有理解为什么这条小溪也没有处理掉。但是,就目前而言,它似乎正常运作。