[MAUI Project Combat] Music Player (1): Übersicht und Architektur

Die Artikelserie erklärt Schritt für Schritt das Kerngeschäft und den Code des Musikplayers:

Warum ist Ihnen dieses Projekt in Erinnerung geblieben?

Dies ist ein altes Projekt für Windows Phone 8. 2014 habe ich als Hobby eine App namens "Tomato Player" geschrieben und nebenbei meine Programmierkenntnisse verbessert.

Die Architektur dieses Projekts wurde mehrfach migriert, von WP8 zu UWP zu Xamarin.Forms. Mit der offiziellen Veröffentlichung von MAUI Ende letzten Jahres habe ich versucht, es auf MAUI zu migrieren.

Obwohl es mehrere Migrationen durchlaufen hat, hat sich der Code des Namensraums und des Wiedergabekerns im Grunde nicht wesentlich geändert.Mit dem Upgrade der Lösung setzt das Projekt auf Änderungen in Bibliotheken und API-Aufrufmethoden, die Microsofts Turbulenzen im mobilen Internet miterlebt haben Feld. Ich habe zufällig festgestellt, dass die vor 8 Jahren an den Microsoft Store übermittelte App immer noch die Download-Seite - den Microsoft App Store - öffnen kann , aber da ich kein Windows Phone-Gerät zur Hand habe, kann ich sie in keinem Emulator zum Laufen bringen . Sie können dieses Objekt und diese Zeit nur aus Store-Screenshots und Quellcode nacherleben.

Dieses Projekt hat jetzt keinen kommerziellen Wert, aber ich weiß, was es für mich bedeutet. Die Freude und Freude, die es mir beim Programmieren bereitete, lässt mich wirklich wissen, was „Code 4 Fun“ ist – — Die Freude, die das Programmieren mit sich bringt eine große Hilfe für mich, die damals gerade in die Gesellschaft eingetreten war, mein Selbstvertrauen aufzubauen und auf dem Weg zu bleiben.

Der Gegenstand hatte möglicherweise nie einen Wert. Dann schreiben Sie Blogbeiträge und machen Sie so viel Wert wie möglich auf Open Source.

Derzeit gibt es auf der .Net-Plattform viele Open-Source-Bibliotheken für Audioverpackungen, wie z eine bessere Möglichkeit haben, es zu implementieren, Willkommen, um eine Nachricht unter dem Artikel zu hinterlassen. Da der Code alt ist und in den letzten Jahren nicht umgestaltet wurde, wird es viele Redundanzen in der C#-Sprachversion und beim Schreiben des Codes geben. Ich möchte mich bei allen hier entschuldigen.

Bildbeschreibung hier einfügen

die Architektur

Unter Verwendung des Abp-Frameworks habe ich bereits geschrieben, wie man Abp in das .NET-MAUI-Projekt portiert , und dieses Projekt ist gemäß diesem Blogbeitrag ebenfalls abgeschlossen.

Plattformübergreifend

Durch die Verwendung von .NET MAU zur plattformübergreifenden Unterstützung können von Xamarin.Forms portierte Anwendungen reibungslos auf Android- und iOS-Plattformen ausgeführt werden.

Der Wiedergabekern wird von partiellen Klassen bereitgestellt, um plattformübergreifende Unterstützung bereitzustellen.In der Ära von Xamarin.Forms müssen Projekte auf verschiedenen Plattformen verwaltet werden.MAUI ist ein einzelnes Projekt, das mehrere Plattformen unterstützt.
MAUI-Anwendungsprojekte enthalten einen Plattformordner, jeder Unterordner stellt eine Plattform dar, auf die .NET MAUI abzielen kann

Jeder Ordner stellt den spezifischen Code für jede Plattform dar, und standardmäßig kompiliert die Kompilierungsphase nur den aktuell ausgewählten Plattformordnercode.

Dies gehört zur Verwendung von partiellen Klassen und Methoden zum Erstellen von plattformspezifischen Inhalten. Weitere Informationen finden Sie in der offiziellen Dokumentation

Zum Beispiel IMusicControlServicein der partiellen Klassenumsetzung im Projekt:

MatoMusic.Core\Impl\MusicControlService.cs
MatoMusic.Core\Platforms\Android\MusicControlService.cs
MatoMusic.Core\Platforms\iOS\MusicControlService.cs
MatoMusic.Core\Platforms\Windows\MusicControlService.cs

Kernklasse

Beim Entwerfen des Wiedergabekerns haben wir den Track-Manager IMusicInfoManagerund den Wiedergabesteuerungsdienst vom Interaktionspfad des Benutzers abstrahiert IMusicControlService.

Das Spielerverhalten und das Streckenbetriebsverhalten sind in ihren jeweiligen Bereichen voneinander isoliert und werden durch das Produktions-Verbrauchs-Modell, den Datenfluss und das Blubbern von Nachrichtenbenachrichtigungen koordiniert. Versuchen Sie, den groß angelegten Einsatz von Thread-Sperren und komplexer Thread-Synchronisationslogik zu vermeiden. In der plattformübergreifenden Lösung werden diese Schnittstellen durch partielle Klassen implementiert, und das Klassendiagramm sieht wie folgt aus:
Bildbeschreibung hier einfügen

Die auf die Musikwiedergabe bezogene Dienstklasse MusicRelatedServicestellt eine Einkapselungsebene des Wiedergabesteuerungsdienstes dar. Im Hinblick auf die eigentliche Player-Geschäftslogik ist es bequemer, den eingekapselten Code zu verwenden, um die Aufgabe abzuschließen.

Das Projekt folgt dem MVVM-Entwurfsmuster. MusicRelatedViewModelAls Basisklasse von ViewModel in Bezug auf die Musikwiedergabe enthält es Track-Manager- IMusicInfoManagerund Playback-Control-Service- IMusicControlServiceObjekte. Durch bidirektionale Bindung können Entwickler die Musiksteuerung und den Track-Zugriff von der Präsentationsschicht aus einfach durchführen.

ViewModelBaseEs ist eine Basisklasse, die vom AbpServiceBaseAufruf der gemeinsamen Funktionen des Abp-Frameworks geerbt ist und diese kapselt. Wie Einstellungs-, Lokalisierungs- und UnitOfWork-Funktionen. Und implementiert INotifyPropertyChangedstellt es Änderungsereignisse für jede Eigenschaft des gebundenen Typs bereit.

Das Kernklassendiagramm sieht wie folgt aus
Bildbeschreibung hier einfügen

Definition

  • Warteschlange - Song-Warteschlange, eine geordnete Liste der aktuell wiedergegebenen Songs
  • Playlist - Playlist, eine Sammlung von spielbaren Inhalten speichern, für Lieblingstitel, zu Favoriten hinzufügen usw.
  • PlaylistEntry – Playlist-Eintrag, abspielbarer Inhalt, verbunden mit lokaler Musik oder Online-Musikinformationen
  • MyFavourite – Mein Favorit, eine spezielle Wiedergabeliste mit der ID 1, die nicht bearbeitet oder gelöscht werden kann und zum Aufnehmen und Aufleuchten des Songs „Little Red Heart“ verwendet wird
  • MusicInfo - Titelinformationen
  • AlbumInfo - Albuminformationen
  • ArtistInfo - Künstlerinformationen
  • BillboardInfo - Charts, Online-Musik-Playlists

Schiene

Zu den Titeln gehören:

  • Titel - Musiktitel
  • AlbumTitle - Albumtitel
  • GroupHeader - die Titelkopfzeile, die verwendet wird, um die Liste entsprechend der Anzeige zu gruppieren
  • URL - Adresse der Audiodatei
  • Künstler - Künstler
  • Genre - Genre
  • IsFavourite - Ist es "Favorit"
  • IsPlaying - ob es spielt
  • AlbumArtPath - Titelbild
  • Dauer - die Gesamtdauer des Songs

Wenn Sie mit dem Fuzzy-Suchsteuerelement kooperieren, muss es implementiert werden.Für IClueObjectdie Verwendungsmethode lesen Sie bitte das AutoComplete-Steuerelement

public class MusicInfo : ObservableObject, IBasicInfo, IClueObject
{ .. }
public List<string> ClueStrings
{
    get
    {
        var result = new List<string>();
        result.Add(Title);
        result.Add(Artist);
        result.Add(AlbumTitle);
        return result;
    }
}

Es erbt von ObservableObject, im Konstruktor Register Property Change Event
IsFavouriteChange, wird aufgerufen MusicInfoManager, um den aktuellen Track als "Favorit" zu setzen oder zu deaktivieren.

private void MusicInfo_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var MusicInfoManager = IocManager.Instance.Resolve<MusicInfoManager>();

    if (e.PropertyName == nameof(IsFavourite))
    {
        if (IsFavourite)
        {
            MusicInfoManager.CreatePlaylistEntryToMyFavourite(this);
        }
        else
        {
            MusicInfoManager.DeletePlaylistEntryFromMyFavourite(this);
        }
    }
}

Track-Sammlung

Eine Titelsammlung ist eine Zusammenfassung von Wiedergabelisten, Musikalben oder von Künstlern (Sängern) erstellter Musik, die Folgendes umfasst:

  • Titel – Titel, Wiedergabeliste, Musikalbum oder Künstlername
  • GroupHeader - die Titelkopfzeile, die verwendet wird, um die Liste entsprechend der Anzeige zu gruppieren
  • Musik - Eine Sammlung von Titelinformationen
  • AlbumArtPath - Titelbild
  • Count - die Anzahl der Titel in der Songsammlung
  • Zeit - die Gesamtdauer der Songsammlung

es erbt vonObservableObject

AlbumInfo, ArtistInfo, PlaylistInfo, BillboardInfosind alle Unterklassen der Track-Sammlung
Bildbeschreibung hier einfügen

MusicsIst der Inhalt der Track-Sammlung, der Typ ist ObservableCollection<MusicInfo>, und das Warteschlangenänderungsereignis wird bei der bidirektionalen Bindung bereitgestellt.

Die Anzahl der Titel in der Sammlung und die Gesamtdauer der Sammlung hängen von dieser Variablen ab

public int Count => Musics.Count();
public string Time
{
    get
    {
        var totalSec = Math.Truncate((double)Musics.Sum(c => (long)c.Duration));
        var totalTime = TimeSpan.FromSeconds(totalSec);
        var time = totalTime.ToString("g");
        return time;
    }
}

Wenn der Inhalt der Sammlung hinzugefügt oder gelöscht wird, werden die Anzahl der Tracks und die Gesamtdauer der Songsammlung synchron mitgeteilt

private void _musics_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Add)
    {
        RaisePropertyChanged(nameof(Time));
        RaisePropertyChanged(nameof(Count));
    }
}

GroupHeaderTitelüberschrift, im Allgemeinen erhalten, ist der erste Buchstabe des Titels, wenn der Titel Chinesisch ist, verwenden Sie die Microsoft.International.Converters.PinYinConverterPinyin-Initialen des ersten Wortes auf Chinesisch, die plattformübergreifende Implementierungsmethode ist wie folgt:

private partial string GetGroupHeader(string title)
{
    string result = string.Empty;
    if (!string.IsNullOrEmpty(title))
    {
        if (Regex.IsMatch(title.Substring(0, 1), @"^[\u4e00-\u9fa5]+$"))
        {
            try
            {
                var chinese = new ChineseChar(title.First());
                result = chinese.Pinyins[0].Substring(0, 1);
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }
        else
        {
            result = title.Substring(0, 1);
        }
    }
    return result;

}

GroupHeaderDer Inhalt, der für die Listengruppenanzeige verwendet wird, wird in nachfolgenden Artikeln ausgearbeitet

Datenbank

Sqlite wird in der Anwendung als Persistenz von Daten wie Wiedergabelisten, Songlisten, Einstellungen usw. verwendet
, und die Sqlite-Datenbankdatei wird mit EF mithilfe von CodeFirst initialisiert:mato.db

Fügen Sie dem MatoMusic.Core-Projekt appsettings.jsoneine lokale SQLite-Verbindungszeichenfolge hinzu

  "ConnectionStrings": {
    "Default": "Data Source=file:{0};"
  },
  ...

Diese Datei ist ein Platzhalter, um den Code-Hardcode an die Konfigurationsdatei zu übergeben

Überschreiben Sie in MatoMusicCoreModule.cs PreInitialize und legen Sie Configuration.DefaultNameOrConnectionString fest:

public override void PreInitialize()
{
    LocalizationConfigurer.Configure(Configuration.Localization);

    Configuration.Settings.Providers.Add<CommonSettingProvider>();

    string documentsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), MatoMusicConsts.LocalizationSourceName);

    var configuration = AppConfigurations.Get(documentsPath, development);
    var connectionString = configuration.GetConnectionString(MatoMusicConsts.ConnectionStringName);

    var dbName = "mato.db";
    string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), MatoMusicConsts.LocalizationSourceName, dbName);

    Configuration.DefaultNameOrConnectionString = String.Format(connectionString, dbPath);
    base.PreInitialize();
}

Definieren Sie als Nächstes die Entitätsklasse

Warteschlange spielen

definiert in\MatoMusic.Core\Models\Entities\Queue.cs

public class Queue : FullAuditedEntity<long>
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override long Id { get; set; }

    public long MusicInfoId { get; set; }

    public int Rank { get; set; }

    public string MusicTitle { get; set; }
}

Lieder Liste

definiert in\MatoMusic.Core\Models\Entities\Playlist.cs

public class Playlist : FullAuditedEntity<long>
{

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override long Id { get; set; }
    public string Title { get; set; }

    public bool IsHidden { get; set; }

    public bool IsRemovable { get; set; }

    public ICollection<PlaylistItem> PlaylistItems { get; set; }
}

Playlist-Eintrag

definiert in\MatoMusic.Core\Models\Entities\PlaylistItem.cs

public class PlaylistItem : FullAuditedEntity<long>
{

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override long Id { get; set; }

    public int Rank { get; set; }

    public long PlaylistId { get; set; }
    [ForeignKey("PlaylistId")]
    
    public Playlist Playlist { get; set; }
    public string MusicTitle { get; set; }

    public long MusicInfoId { get; set; }
}


Aufbau

Das Datenbankkontextobjekt MatoMusicDbContextist wie folgt definiert

public class MatoMusicDbContext : AbpDbContext
{
    //Add DbSet properties for your entities...

    public DbSet<Queue> Queue { get; set; }
    public DbSet<Playlist> Playlist { get; set; }
    public DbSet<PlaylistItem> PlaylistItem { get; set; }

    ...

MatoMusic.EntityFrameworkCore ist ein Wartungs- und Verwaltungsprojekt für Anwendungsdatenbanken, das von Abp.EntityFrameworkCore abhängt.
Verweisen Sie in der csproj-Datei im MatoMusic.EntityFrameworkCore-Projekt auf die folgenden Pakete

<PackageReference Include="Abp.EntityFrameworkCore" Version="7.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">

mato.dbIm Projekt MatoMusicEntityFrameworkCoreModule.cs wird das Kontextobjekt registriert, und die Migration wird bei der Programminitialisierung ausgeführt, und die Datei wird auf dem Gerät generiert

public override void PostInitialize()
{
    Helper.WithDbContextHelper.WithDbContext<MatoMusicDbContext>(IocManager, RunMigrate);
    if (!SkipDbSeed)
    {
        SeedHelper.SeedHostDb(IocManager);
    }
}

public static void RunMigrate(MatoMusicDbContext dbContext)
{
    dbContext.Database.Migrate();
}

Projektadresse

GitHub:MatoMusic

Das nächste Kapitel stellt die Kernfunktionen des Players vor: die Wiedergabedienstklasse

Acho que você gosta

Origin blog.csdn.net/jevonsflash/article/details/128960586
Recomendado
Clasificación