我写了一个小工具来下载一个电台播放列表让我浏览,非常小而简单,而且很好用。但由于某种原因,对于略高于1k的项目(小于3Mb ob数据),该应用程序需要几乎1.4Gb的RAM。因此,要么是我没有看到内存泄漏,要么是我以不应该的方式使用了集合视图,要么是其他地方有bug(例如。在MAUI本身)。
我的应用程序是一个新的MAUI项目在VS中,只有MainPage文件被修改,我不想把这个小代码分散在多个文件上。代码如下:
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Ö3_Playlist"
x:Class="Ö3_Playlist.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Button
x:Name="CounterBtn"
Text="Parse"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
<ActivityIndicator IsVisible="{Binding IsBusy}" Color="White"/>
<CollectionView ItemsSource="{Binding Entries}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:SongEntry">
<HorizontalStackLayout HorizontalOptions="FillAndExpand">
<Button Text="Open" Command="{Binding OpenCommand}"/>
<Entry Text="{Binding Name}" IsReadOnly="True"/>
<Button Text="{Binding IsLiked}" Command="{Binding ClickedCommand}"/>
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
MainPage.cs
public partial class SongEntry : ObservableObject
{
[BsonId]
public string Name { get; set; }
[ObservableProperty]
public int isLiked;
[RelayCommand]
private void Clicked()
{
if (isLiked == 0) IsLiked = 1;
else if (isLiked == 1) IsLiked = -1;
else IsLiked = 0;
Database.Save(this);
}
[RelayCommand]
private async void Open()
{
string uri = @"https://www.youtube.com/results?search_query=" + Name;
await BrowserOpen_Clicked(uri);
}
private async Task BrowserOpen_Clicked(string url)
{
try
{
Uri uri = new Uri(url);
await Browser.Default.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
}
catch (Exception ex)
{
// An unexpected error occurred. No browser may be installed on the device.
}
}
}
public class WebLoader
{
public IConfiguration AngleSharpConfiguration { get; set; }
public IBrowsingContext AngleSharpContext { get; set; }
public WebLoader()
{
AngleSharpConfiguration = Configuration.Default.WithDefaultLoader();
AngleSharpContext = BrowsingContext.New(AngleSharpConfiguration);
}
public virtual async Task<IDocument> LoadWebpage(string url, int retries = 10)
{
IDocument document;
int counter = 0;
do
{
document = await AngleSharpContext.OpenAsync(url);
counter++;
} while (document == null || (document?.Body.ChildElementCount == 0 && counter < retries));
return document;
}
}
public class Database
{
static string dbFile = @"C:\SomePath\dbFile.db";
public static IList<SongEntry> GetSongs()
{
IList<SongEntry> songs;
using (var db = new LiteDatabase(dbFile))
{
songs = db.GetCollection<SongEntry>("Entries").FindAll().ToList<SongEntry>();
}
return songs;
}
public static void Save(IList<SongEntry> entries)
{
using (var db = new LiteDatabase(dbFile))
{
foreach(var e in entries)
db.GetCollection<SongEntry>("Entries").Upsert(e);
}
}
public static void Save(SongEntry entry)
{
using (var db = new LiteDatabase(dbFile))
{
db.GetCollection<SongEntry>("Entries").Upsert(entry);
}
}
public static void Insert(SongEntry entry)
{
using (var db = new LiteDatabase(dbFile))
{
db.GetCollection<SongEntry>("Entries").Insert(entry);
}
}
}
public partial class ViewModel : ObservableObject
{
string dbFile = @"C:\Users\Thorsten\Desktop\Ö3_Playlist_Review.db";
[ObservableProperty]
IList<SongEntry> entries = new List<SongEntry>();
[ObservableProperty]
bool isBusy = false;
public ViewModel()
{
Entries = Database.GetSongs();
}
~ViewModel()
{
Database.Save(Entries);
}
public async Task Parse()
{
IsBusy = true;
var loader = new WebLoader();
for (int i = 0; i < 10; i++)
{
var doc = await loader.LoadWebpage(@"https://onlineradiobox.com/at/hitradiooe3/playlist/" + i);
var list = GetSongs(doc);
foreach (var song in list)
{
if (Entries.FirstOrDefault(x => x.Name.Trim().ToLower() == song.Name.Trim().ToLower()) == null)
{
Database.Insert(song);
Entries.Add(song);
}
}
}
IsBusy = false;
}
private IList<SongEntry> GetSongs(IDocument doc)
{
IList<SongEntry> list = new List<SongEntry>();
var tmp = doc.Body.GetElementsByClassName("track_history_item");
foreach (var item in tmp)
{
string name = item.Text().Trim();
var s = new SongEntry() { Name = name };
list.Add(s);
}
return list;
}
}
public partial class MainPage : ContentPage
{
public ViewModel vm { get; set; } = new ViewModel();
public MainPage()
{
BindingContext = vm;
InitializeComponent();
}
private async void OnCounterClicked(object sender, EventArgs e)
{
await vm.Parse();
}
}
有人能看出问题吗?
1条答案
按热度按时间zf9nrax11#
我相信你不能把CollectionView放在ScrollView中,因为它最终会一次呈现所有内容,而不是使用虚拟滚动。