すべて、Xamarin ProgressBarがリアルタイムで更新されない
私はXamarinにかなり新しく、C#ですので、親切にしてください!
DependencyServiceを使用して.iOSにドロップするXamarin.Formsアプリケーションがあります。このアプリケーションは、デバイス上のすべての曲をトラバースし、カスタム "Song"モデルを使用して戻ります。
これはもっと良い方法ですが、アルバムアートワークをPCLに戻すには、iOS UIImageを使ってSystem.IO.Streamオブジェクトに変換し、それをソングモデル。
このアートワーク機能を追加すると、各曲を処理する際のオーバーヘッドが大幅に増加しました。ユーザーに何が起こっているのかを感謝するために、ページに進行状況バーを置き、1つの曲を処理するたびに更新するようにしました。
私の問題は、進行状況バーをリアルタイムで更新することができなかったことです。プロセスが完了すると更新されます。
...これはXAMLページです...
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestApplication" x:Class="TestApplication.TestApplicationPage">
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Button Text="No. of Songs" Clicked="GetNoOfSongs"></Button>
<ProgressBar Margin="20" x:Name="progressBar" Progress="{Binding Progress}" WidthRequest="400"></ProgressBar>
</StackLayout>
</ContentPage>
これがあると、私はこの段階でMVVMを使用していないので、これは背後にあるコードである...
using Xamarin.Forms;
using TestApplication.Interfaces;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System;
namespace TestApplication
{
public partial class TestApplicationPage : ContentPage, INotifyPropertyChanged
{
private double _progress;
public double Progress
{
get { return _progress; }
set
{
_progress = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public TestApplication()
{
InitializeComponent();
BindingContext = this;
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
async void GetNoOfSongs(object sender, System.EventArgs e)
{
Action<double> progressUpdate = UpdateProgress;
var songs = await DependencyService.Get<IMedia>().GetSongs(progressUpdate);
await DisplayAlert("No. of Songs", string.Format("You have { 0} songs on your device!", songs.Count), "Ok");
}
void UpdateProgress(double obj)
{
Progress = (double)obj;
}
}
}
ソングモデル...
using System;
using System.IO;
namespace TestApplication.Models
{
public class Song
{
public string Artist { get; set; }
public string Album { get; set; }
public string Title { get; set; }
public Stream Artwork { get; set; }
public TimeSpan Duration { get; set; }
}
}
が...これは...
012 IMEDIAインタフェースでありますusing System.Threading.Tasks;
using System.Collections.Generic;
using TestApplication.Models;
using System;
namespace TestApplication.Interfaces
{
public interface IMedia
{
Task<bool> IsAuthorised();
Task<List<Song>> GetSongs(Action<double> callback);
}
}
...と、これは.iOSプロジェクト内DependencyService実装です...
using TestApplication.Interfaces;
using TestApplication.Models;
using MediaPlayer;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
[assembly: Xamarin.Forms.Dependency(typeof(TestApplication.iOS.Media))]
namespace TestApplication.iOS
{
public class Media : IMedia
{
public List<Song> Songs { get; private set; }
public async Task<bool> IsAuthorised()
{
await MPMediaLibrary.RequestAuthorizationAsync();
if (MPMediaLibrary.AuthorizationStatus == MPMediaLibraryAuthorizationStatus.Authorized)
return true;
else
return false;
}
public async Task<List<Song>> GetSongs(Action<double> callback)
{
Songs = new List<Song> { };
if (await IsAuthorised())
{
var songs = MPMediaQuery.SongsQuery.Items;
double index = 0;
foreach (var song in songs)
{
index++;
callback.Invoke(index/songs.Length);
Stream artwork = null;
if (song.Artwork != null)
artwork = song.Artwork.ImageWithSize(song.Artwork.Bounds.Size).AsPNG().AsStream();
Songs.Add(new Song
{
Artist = song.AlbumArtist,
Album = song.AlbumTitle,
Title = song.Title,
Artwork = artwork,
Duration = TimeSpan.FromSeconds(song.PlaybackDuration),
});
}
}
return Songs;
}
}
}
...私はプロパティに進捗値をバインドしました表示されます。たぶん、この機能の目的のために、ProgressBarオブジェクトを実行してもそれを更新することはできますが、バインディングが機能していることがわかります。
私はそれがオンザフライで更新されていない理由について私の指を置くことはできません。デバッグすると、コールバックに入り、プロパティを更新してOnPropertyChangedイベントを発生させますが、UIは最後まで更新されません。
私はそれが非同期/待望のものと何か関係があるとは思っていますが、確信が持てません。
誰かが私のための答えを持っていると確信しており、今後の助けに感謝しています。
おかげ
頭の上に私はあなたがあなたのストリームを大幅に削減するbase64文字列に変換することをお勧めオーバーヘッド –
ありがとう、それもチェックします。このスレッドの主な目的は、プログレスバーが正しく更新されるようにすることでした。オーバヘッドでは、動作時にははるかに明確ですが、パフォーマンスにはBase64をチェックします。 –