2016-06-27 12 views
0

私は問題を説明するために英語で最善を尽くします。 私は現在、XamarinがIOSアプリケーションとAndroid Appをこの上で移行するかどうかを確認しようとしています。なぜなら、これは本当にいいと思われるからです。Xamarin IOSはcontoller非同期タスクを作成できません

小さなテストでは、単純なログインページをテストしています。私は愚かな、簡単な質問をする場合

は私が最初の実装は、この記事の最後に、問題を紹介します...事前に

とても残念、CSHARPには本当に新しいです。

[実装]

だからこれは私がナゲットからRestSharp (Rest library client)ライブラリを使用してやったものです。私は、Android AppとIOsアプリで使用される共有プロジェクトを持っています(ジョブを1回だけ作成するため)。私はMacのXamarin Studioで作業しています。

public interface UserConnectionStates 
    { 
     //Regroup all state created above 
     void userIsConnected(User user); 
     void userConnectionFailed(IRestResponse<User> response); 
     void userDisconnected(); 
} 

public class LoginApiManager : RestManager 
{ 
    //Used for instance and shared element 
    public static LoginApiManager instance; 

    //Permits to store the information about the current loged in user 
    private User loggedInUser; 

    //All listeners for that class 
    private List<UserConnectionStates> userConnectionStatesListeners = new List<UserConnectionStates>(); 

    public LoginApiManager() 
    { 
     //Create the the Rest Client to make Api Calls 
     base.client = new RestClient(); 
     client.BaseUrl = new Uri(apiPath); 
     client.Authenticator = new HttpBasicAuthenticator(null, null); 
    } 

    public static LoginApiManager getInstance() 
    { 
     if (instance != null) 
     { 
      return instance; 
     } 
     else 
     { 
      return new LoginApiManager(); 
     } 
    } 

    //------- UserConnectionStates Listeners accessors -------- 
    public void addUserConnectionStatesListener(UserConnectionStates listener) 
    { 

     if (!userConnectionStatesListeners.Contains(listener)) 
     { 
      userConnectionStatesListeners.Add(listener); 
     } 

    } 

    public void removeUserConnectionStatesListener(UserConnectionStates listener) 
    { 
     if (userConnectionStatesListeners.Contains(listener)) 
     { 
      userConnectionStatesListeners.Remove(listener); 
     } 
    } 

    /* 
    * Permits to connect a user with a given username and password. It will 
    * call the API and return a User Object containing all information needed 
    * for connection, including token. 
    */ 
    public void connectUserWithUserNameAndPassword(string username, string password) 
    { 

     var request = new RestRequest(Method.POST); 
     request.Resource = "/myApiEndpoints/"; 

     //Add it to the request 
     request.AddParameter("username", username); 
     request.AddParameter("password", password); 

     //Execute the query 
     client.ExecuteAsync<User>(request, (response) => 
     { 
      if (response.StatusCode == System.Net.HttpStatusCode.OK) 
      { 
       //We serialize the user from response 
       loggedInUser = response.Data; 
       foreach (var l in this.userConnectionStatesListeners) 
       { 
        l.userIsConnected(response.Data); 
       } 

      } 
      else 
      { 
       //We send error to the code 
       foreach(var l in this.userConnectionStatesListeners) 
       { 
        l.userConnectionFailed(response); 
       } 
      } 

     }); 
    } 
} 

は... [OK]を、私のLoginViewControllerインタフェースUserConnectionStatesを実装し、するために、リスナーのリストに自分自身を参照し、続けていきましょう:私のLoginApiManager.csで

は、私はこのような「基本」の実装を持っていますさまざまな接続状態の変更について通知を受けることができます。ただ、このように:私のLoginController.csで

public partial class LoginController : UIViewController, UserConnectionStates 
{ 
    //Some code here ... 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     loginManager = LoginApiManager.getInstance(); 
     loginManager.addUserConnectionStatesListener(this); //we create a listener for information about user connection 

    } 

    //Here comme the interface methods... 

    //Interface for listening user connection state 
    public void userIsConnected(User user) 
    { 
     var alertController = UIAlertController.Create("Connexion", "Connexion Success!",UIAlertControllerStyle.Alert); 
     alertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null)); 
     this.PresentViewController(alertController, true, null); 

    } 

    public void userConnectionFailed(IRestResponse<User> response) 
    { 
     var alert= UIAlertController.Create("Connexion", "Unable to connect", UIAlertControllerStyle.Alert); 
     alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null)); 
     PresentViewController(alert, animated: true, completionHandler: null); 
    } 

    public void userDisconnected() 
    { 

    } 

} 

[問題]

...ここに私の問題は、あるときclient.ExecuteAsync(要求、(レスポンス))成功の例としてが呼び出され、リスナオブジェクトによって実装されたインターフェイスメソッドを呼び出すpublic void userIsConnected(User user)、私のLoginControllerのですが、それは他のスレッドで呼び出されているため、

var alertController = UIAlertController.Create("Connexion", "Connexion Success!",UIAlertControllerStyle.Alert); 

nosが停止して何もしません。

私はシンプル

IRestResponse response = client.Execute(request); 

を使用してテストを行い、この方法は、同期と同じスレッドで呼び出されますが、タスクが完了するまで、それがUIをロック...

ので、それは動作しますこの種のパターンを実装するには、CSharpやXamarinの最善の方法は何ですか?このようなことをする別の方法があるなら、私はそれを学ぶでしょうが、私はこれに新しいので、私はこの種のもののベストプラクティスを知らず、ドキュメントでこれを見つけられませんでした。確かにそれでは、それは申し訳ありませんが見つかりません)。あなたの助けを事前に

多くのおかげで、

よろしく、 ケビン

+0

おそらくこれはあなたを助けます:https://msdn.microsoft.com/en-us/magazine/dn605875.aspx?f=255&MSPPError=-2147217396 –

+0

ありがとう、私は見てみましょう! – kevzzz

答えて

0

は、私はあなたの現在のコードの構造を再考だろう正直に言うと。まず第一に、私はRestSharpの使用を停止してのために行くだろう:あなたのiOSとAndroidのアプリケーションでMobile resiliency with Xamarin

使用MVVM:Refit

これは適切にコードを構造化する方法についていくつかの光を当てることがかなりクールポストがあります。これにより、ViewModelを共有し、再利用可能で分離されたコードを増やすことができます。

+0

あなたのお手伝いとポストに感謝します。私は@ TomaszKowalczykの答えに関連して、このアプローチで深く行くつもりです。あなたのアドバイスに従って最良のアプローチを採用するために、私は早期にマイグレーションをやめました。コードに戻ってみましょう:-)。 – kevzzz

+0

@kevzzz happy coding1 :-) – Mittchel

関連する問題