清除应用程序内存/取消注册服务/在应用程序内重新登录

问题描述 投票:0回答:1

我不知道如何描述标题,抱歉。

我正在使用 .net Maui。 我面临的问题很难解释,所以我会添加尽可能多的代码,希望能解决这个问题。

我有登录和注销页面。 当应用程序启动时,我使用此代码

public App()
{
    InitializeComponent();

    try
    {
        var accountIdKey = Preferences.Get("AccountIdKey", string.Empty);
        var accountEmailKey = Preferences.Get("AccountEmailKey", string.Empty);

        if (!string.IsNullOrEmpty(Preferences.Get("FirebaseRefresher", "")) && !string.IsNullOrEmpty(accountIdKey))
        {
            var authToken = SecureStorage.GetAsync("AuthToken").Result;
            var firebaseHelper = new FirebaseHelper(accountEmailKey, authToken);

            MainPage = new AppShell();
        }
        else
        {
            MainPage = new NavigationPage(new LogInPage());
        }
    }
    catch
    {
        MainPage = new NavigationPage(new LogInPage());
    }
}

我注册了这样的服务(在 MauiProgran.cs 中)

builder.Services.AddSingleton<IProductService, ProductService>();
builder.Services.AddSingleton<ProductList>();
builder.Services.AddSingleton<SettingsPage>();
builder.Services.AddSingleton<ProductListViewModel>();
builder.Services.AddSingleton<SettingsViewModel>();
builder.Services.AddSingleton<AccountViewModel>();

这就是我登录的方式(AccountViewModel)

public class AccountViewModel : BaseViewModel
{
    IAccountService accountService;
public string WebAPIKey = "my_web_api_key";
private string emailFromAuth;

public AccountViewModel()
{
}

public AccountViewModel(IAccountService accountService)
{
    this.accountService = accountService;
}

        public ICommand LogInCommand => new Command<Tuple<object, object>>(async (parameters) =>
        {
            string userEmailEntry = "";
            string userPasswordEntry = "";

            if (parameters != null && parameters.Item1 is Entry emailEntry && parameters.Item2 is Entry passwordEntry)
            {
                userEmailEntry = emailEntry.Text;
                userPasswordEntry = passwordEntry.Text;
            }

            var authProvider = new FirebaseAuthProvider(new FirebaseConfig(WebAPIKey));

            var auth = await authProvider.SignInWithEmailAndPasswordAsync(userEmailEntry.ToLower(), userPasswordEntry);
            var emailVerified = auth.User.IsEmailVerified;

            if (emailVerified)
            {
                await SecureStorage.SetAsync("AuthToken", auth.FirebaseToken);

                var firebaseClient = new FirebaseClient("https://app-name.firebasedatabase.app/",
                  new FirebaseOptions
                  {
                      AuthTokenAsyncFactory = () => Task.FromResult(auth.FirebaseToken)
                  });

                var userEmail = userEmailEntry.ToLower().Replace(".", "_");
                var userFromDB = await firebaseClient.Child(userEmail).Child("User").OnceSingleAsync<AccountProfile>();

                AccountProfile accountProfile = new();
                if (userFromDB == null)
                {
                    accountProfile = new AccountProfile
                    {
                        AccountId = Guid.NewGuid(),
                        AccountEmail = userEmailEntry.ToLower()
                    };

                    await firebaseClient.Child(userEmail).Child("User").PutAsync(accountProfile);
                }

                else
                {
                    accountProfile.AccountId = userFromDB.AccountId;
                    accountProfile.AccountEmail = userFromDB.AccountEmail;
                }

                var firebaseHelper = new FirebaseHelper(accountProfile.AccountEmail, auth.FirebaseToken);

                var content = await auth.GetFreshAuthAsync();
                var serializedcontent = JsonConvert.SerializeObject(content);
                Preferences.Set("FirebaseRefresher", serializedcontent);
                Preferences.Set("UserEmailKey", userEmailEntry.ToLower());

                App.Current.MainPage = new AppShell();
            }
            else { }
        });
}

而且,这是 FirebaseHelper

public class FirebaseHelper
{
private static FirebaseHelper instance = null;
public static FirebaseHelper Instance
{
    get
    {
        if (instance == null)
            throw new Exception("Null instance.");
        return instance;
    }
}

private string _accountEmail;
private string _authToken;
FirebaseClient firebaseClient;

public FirebaseHelper(string accountEmail, string authToken)
{
    _accountEmail = accountEmail.Replace(".", "_");
    _authToken = authToken;
    instance = this;

    firebaseClient = new FirebaseClient("https://app-name.firebasedatabase.app",
    new FirebaseOptions
    {
        AuthTokenAsyncFactory = () => Task.FromResult(_authToken)
    });
}

public void ClearInstance()
{
    instance = null;
}

public async Task<List<Product>> GetAllProductsAsync()
{
    return (await firebaseClient.Child(_accountEmail).Child("Products")
      .OnceAsync<Product>()).Select(p => p.Object).ToList();
}
}

因为我几乎包含了我的整个项目......这就是我获取列表的方式

public partial class ProductListViewModel : BaseViewModel
{
    readonly IProductService productService;
    public ObservableCollection<Product> ProductList { get; set; } = new();

    public ProductListViewModel(IProductService productService)
    {
        this.productService = productService;
        (GetAllProductsCommand = new Command(async () => await GetAllProducts())).Execute(null);
    }

    public ICommand GetAllProductsCommand { get; }
    public async Task GetAllProducts()
    {
        try
        {
            var products = await productService.GetAllProductsAsync();

            if (ProductList.Count != 0)
                ProductList.Clear();

            ProductList.AddRange(products);
        }
        catch {}
    }
}

所以...这就是我登录的完整方式。

这是我的注销代码

public class SettingsViewModel
{
public ICommand LogOutCommand => new Command(async () =>
{
    Preferences.Remove("AccountIdKey", string.Empty);
    Preferences.Remove("AccountEmailKey", string.Empty);

    try
    {
        Helper.FirebaseHelper.Instance.ClearInstance();
        Preferences.Remove("FirebaseRefresher");
    }
    catch { }

    Application.Current.MainPage = new NavigationPage(new LogInPage());
});
}

一切都运转良好。 但是,当我登录时,应用程序会遍历(初始化)所有 Viewmodel、FirebaseHelper 等...... 我通过登录用户(我称之为 User1)获得

ProductList

问题是: 当我注销时,它会将我带到“LogInPage”,如果我使用不同的用户(比方说 User2)登录,它仍然会记住 User1 并且不会通过(初始化)Viewmodels、FirebaseHelper 等... 并且它没有更新

ProductList
(它显示了 User1 的
ProductList
) 而且,在该代码上

public async Task<List<Product>> GetAllProductsAsync()
{
    return (await firebaseClient.Child(_accountEmail).Child("Products")
      .OnceAsync<Product>()).Select(p => p.Object).ToList();
}

"_accountEmail"
显示的是 User1 电子邮件而不是 User2

最后一件事,如果我注销并重新启动应用程序......一切正常。

我知道这是一个很长的故事,我只是没有找到任何简单的方法来解释这个问题。

非常感谢。

xamarin.forms maui
1个回答
0
投票

在注册中使用

AddSingleton<T>
时,这意味着该对象的单个实例将在应用程序的生命周期中保留。

在注册中使用

AddTransient<T>
时,它将在解析期间根据请求创建对象的新实例。

这种情况的解决方法是将

AddSingleton<T>
更改为
AddTransient<T>
。然后,当您执行导航时,将重新创建注册的视图模型。另外,
_accountEmail
字段应更改为静态。

更多信息可以参考依赖注入注册

© www.soinside.com 2019 - 2024. All rights reserved.