Как использовать Xamarin.Firebase.Auth в неактивном классе и получать уведомления? - PullRequest
0 голосов
/ 30 октября 2018

Я хочу инкапсулировать FirebaseAuth в класс AuthService .

Я также могу войти в систему ... Но я не могу получить событие от Firebase, так как он не может уведомлять моих слушателей внутри класса AuthService.

Когда я нажимаю кнопку входа в LoginActivity, я вижу в консоли, что пользователь вошел в систему.

10-29 21: 45: 34.519 D / FirebaseAuth (28144): Уведомление слушателей токена id о пользователе (mvBkX8YferS6XVdqnUeSLu2yldp2).

10-29 21: 45: 34.527 D / FirebaseApp (28144): уведомление слушателей состояния авторизации.

10-29 21: 45: 34.528 D / FirebaseApp (28144): уведомлено 0 слушателей состояния авторизации.

Вот класс AuthService:

 public class AuthService : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
    public User CurrentUser;
    private FirebaseAuth firebaseAuth;

    private static AuthService _instance = null;
    private static System.Object _mutex = new object();

    public IntPtr Handle {get;}

    public static AuthService GetInstance()
    {
        if (_instance == null)
        {
            lock (_mutex) // now I can claim some form of thread safety...
            {
                if (_instance == null)
                {
                    _instance = new AuthService();
                }
            }
        }
        return _instance;
    }

    public AuthService()
    {
       Initialise();
    }

    private void Initialise()
    {
        this.firebaseAuth = FirebaseAuth.Instance;

        if (FirebaseAuth.Instance.CurrentUser != null)
        {
            this.CurrentUser = User.GetInstance();
        }
    }

    public FirebaseUser GetUser()
    {
        FirebaseUser user;

        if (FirebaseAuth.Instance.CurrentUser != null)
        {
            user = FirebaseAuth.Instance.CurrentUser;
        }
        else
        {
            user = null;
        }
        return user;
    }


    public void SignInWithEmailAndPassword(string email, string password)
    {
        FirebaseAuth.Instance.SignInWithEmailAndPassword(email, password)
            .AddOnSuccessListener(this)
            .AddOnFailureListener(this);
    }

    public void OnSuccess(Java.Lang.Object result)
    {
        this.CurrentUser = User.GetInstance();

        MyApplication.Context.StartActivity(typeof(MainActivity));
    }
  }
}

LoginActivity:

 public class LoginActivity : Activity
{
    AuthService _AuthService;
    private EditText loginMail;
    private EditText loginPassword;
    private Button buttonLogin;
    private Button buttonGoToCreateAccount;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_login);

        loginMail = FindViewById<EditText>(Resource.Id.emaillogin);
        loginPassword = FindViewById<EditText>(Resource.Id.passwordlogin);
        buttonLogin = FindViewById<Button>(Resource.Id.loginbutton);

        buttonLogin.Click += (sender, e) =>
        {
        AuthService.GetInstance().SignInWithEmailAndPassword(loginMail.Text, loginPassword.Text);
        };
    }
}

Почему прослушиватель OnSuccess, реализованный в неактивный класс, не смог получить событие. Я уже заставил FirebaseAuth работать напрямую из Activity, но я хочу инкапсулировать аутентификацию.

У кого-нибудь есть подсказка?

1 Ответ

0 голосов
/ 01 ноября 2018

Мне наконец-то удалось это сделать.

Вот класс слушателя для аутентификации AuthListeners :

 public class AuthListener : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
    public delegate void OnAuthFailure(string error);
    public event OnAuthFailure OnAuthFailureEvent;

    public delegate void OnAuthSuccess();
    public event OnAuthSuccess OnAuthSuccessEvent;

    public AuthListener()
    {
    }

    public void OnSuccess(Java.Lang.Object result)
    {
        Console.WriteLine("success");
        OnAuthSuccessEvent?.Invoke();
    }

    public void OnFailure(Java.Lang.Exception e)
    {
        Console.WriteLine("failure: " + e.Message);
        OnAuthFailureEvent?.Invoke(e.Message);
    }
}

Вот класс AuthService :

 public class AuthService
{
    private FirebaseAuth firebaseAuth;

    public AuthService()
    {
       Initialise();
    }

    private void Initialise()
    {
        this.firebaseAuth = FirebaseAuth.Instance;
    }    

    public void SignInWithEmailAndPassword(string email, string password, AuthListener authListener)
    {
        FirebaseAuth.Instance.SignInWithEmailAndPassword(email, password)
            .AddOnSuccessListener(authListener)
            .AddOnFailureListener(authListener);
    }

    public void CreateUserWithEmailAndPassword(string email, string password, string userName, AuthListener authListener)
    {
        FirebaseAuth.Instance.CreateUserWithEmailAndPassword(email, password)
            .AddOnFailureListener(authListener)
            .AddOnSuccessListener(authListener);
    }

    public void SignOut()
    {
        FirebaseAuth.Instance.SignOut();
    }
}

Затем во фрагменте входа || create_account || я просто вызываю службу Auth и подписываюсь на событие от AuthListeners.

Пример с LoginActivity :

 public class LoginActivity : Activity
{
    AuthListener _authListener;
    AuthService _authService;

    private EditText loginMail;
    private EditText loginPassword;
    private Button buttonLogin;
    private Button buttonGoToCreateAccount;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_login);

        _authListener = new AuthListener();
        _authService = new AuthService();
        Subscribe();

        loginMail = FindViewById<EditText>(Resource.Id.emaillogin);
        loginPassword = FindViewById<EditText>(Resource.Id.passwordlogin);
        buttonLogin = FindViewById<Button>(Resource.Id.loginbutton);
        buttonGoToCreateAccount = FindViewById<Button>(Resource.Id.goto_create_account);


        buttonLogin.Click += (sender, e) =>
        {
            _authService.SignInWithEmailAndPassword(loginMail.Text, loginPassword.Text, this._authListener );
        };

        buttonGoToCreateAccount.Click += (sender, e) =>
        {
            UnSubscribe();

            StartActivity(typeof(CreateAccountActivity));
            Finish();
        };
    }

    private void UnSubscribe()
    {
        _authListener.OnAuthFailureEvent -= ShowErrorDialog;
        _authListener.OnAuthSuccessEvent -= AuthSuccess;
    }

    private void Subscribe()
    {
        _authListener.OnAuthFailureEvent += ShowErrorDialog;
        _authListener.OnAuthSuccessEvent += AuthSuccess;
    }

    private void AuthSuccess()
    {
        StartActivity(typeof(DashboardActivity));
        Finish();
    }

    private void ShowErrorDialog(string error)
    {
        this.RunOnUiThread(() =>
        {
            AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
            alertDialog.SetTitle("Error");
            alertDialog.SetMessage(error);
            alertDialog.SetNeutralButton("Try again!", delegate
            {
                alertDialog.Dispose();
            });
            alertDialog.Show();
        });
    }
}

Теперь я могу утверждать, что я инкапсулировал службу аутентификации Firebase, поэтому однажды, если я, наконец, захочу оставить базу Firebase для другой службы, это не будет беспорядок или, по крайней мере, полный беспорядок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...