亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何將 StartActivityForResult 事件注冊到 ViewModel?[MVVM]

如何將 StartActivityForResult 事件注冊到 ViewModel?[MVVM]

慕工程0101907 2023-06-08 20:03:20
我在使用 Java 中的 MVVM 實現 Google 登錄時遇到問題。在這里,您將以正常方式看到來自 Google 的示例代碼:問題:在你的活動中:@Overridepublic void onCreate(Bundle savedInstanceState) {    /* Here is the Issue:     * Google Object is defined in View - Activity     * I would like to have Google Object defined in my ViewModel     */    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build();    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);}// when Google Button CLicked@Overridepublic void onClick(View v) { signIn(); }private void signIn() {    /* Here is the Issue:     * I have to get this process done in View Model     * so view will not reference any Google Object     */    Intent signInIntent = mGoogleSignInClient.getSignInIntent();    startActivityForResult(signInIntent, RC_SIGN_IN);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    // Below will be processed in ViewModel    GoogleSignInClient.getSignInIntent(...);    if (requestCode == RC_SIGN_IN) {        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);        handleSignInResult(task);    }}問題: *見評論所以我想出了下面的想法:在活動中:// when Google Button CLicked@Overridepublic void onClick(View v) { viewModel.loginGoogle(); }private void subscribeUi() {    // register startActivityForResult Event to ViewModel and set this activity as receiver...    // viewModel.startActivityForResultEvent.setEventReceiver(this Activity)    // How to do this?}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {    // send the result to View Model    viewModel.onResultFromActivity(requestCode,resultCode,data);    // escallate to super    super.onActivityResult(requestCode, resultCode, data)}
查看完整描述

4 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

我認為您可以執行以下操作,它不持有全局引用,context因此不會泄漏


  public void loginGoogle(Context context){


         if(isSigningIn)

            return


         context.startActivityForResult(getGoogleSignInIntent(), GOOGLE_SIGN_IN)

         isSigningIn = true;

    }


查看完整回答
反對 回復 2023-06-08
?
臨摹微笑

TA貢獻1982條經驗 獲得超2個贊

替換 startActivityForResult 的文檔和函數似乎不鼓勵這樣做:

注冊請求以啟動由給定合同指定的結果活動。這會在與此調用者關聯的注冊表中創建一個記錄,管理請求代碼,以及在后臺與 Intent 的轉換。這必須無條件調用,作為初始化路徑的一部分,通常作為 Activity 或 Fragment 的字段初始化程序。如果此片段的宿主是 ActivityResultRegistryOwner,則將使用宿主的 ActivityResultRegistry。否則,這將使用片段的活動注冊表。

注意“This must be called unconditionally, as part of initialization path”。

另請注意此 IlliegalStateException 消息:

片段 [this] 在創建后嘗試注冊 ForActivityResult。片段必須在創建之前調用“registerForActivityResult()”(即初始化、“onAttach() 或 onCreate())”。

所以我的建議是將契約和registerForActivityResult()你的 Activity 或 FragmentonCreate放在你的視圖模型/域類中的函數中,無論你將對結果做什么,這基本上就是你已經在做的事情。


查看完整回答
反對 回復 2023-06-08
?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

您可以使用 SingleLiveData 打開新屏幕。

  1. 您創建具有所有必要參數的類來啟動活動

  2. 在 ViewModel 中,您使用需要的參數創建此類

  3. 您在 ViewModel 中創建單個實時數據字段并從活動/片段中觀察它

  4. 你用 SingleLiveData 發送這個類

創建類:

public Enum Screen {

? ?LOGIN

}

在視圖模型中:


...


private SingleLiveData<Screen> onOpenScreen = new SingleLiveData<Screen>()


public SingleLiveData<Screen> observeScreenOpen() {

? ? return onOpenScreen

}


public void loginGoogle(){

? ? onOpenScreen.value = Screen.LOGIN

}


...

在活動/片段中


viewModel.observeScreenOpen(this, new Observer<Screen> {screen->

? ? if(screen == Screen.LOGIN) {

? ? ? ? //start your activity here

? ? }

})


查看完整回答
反對 回復 2023-06-08
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

我要做的是在被調用的 ViewModel 中注冊一個回調,Activity 可以對其做出反應。然后 ViewModel 可以擁有大部分業務邏輯,但不必引用 Activity 或 Context,Activity 可以處理啟動 Intent 的 Activity 特定內容。


例子:


回調接口:


interface OnSignInStartedListener {

    void onSignInStarted(GoogleSignInClient client);

}

視圖模型:


public class ViewModel {

    private final OnSignInStartedListener mListener;


    public ViewModel(OnSignInStartedListener listener) {

        mListener = listener;

    }


    public void viewModelOnCreate() {

        // This is what i want: Google object defined in View Model

        // but I dont know how to call startActivityForResult from here?

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build();

        mGoogleSignInClient = GoogleSignIn.getClient(getApplication(), gso);

    }


    public void loginGoogle() {

        // Invoke callback here to notify Activity

        mListener.onSignInStarted(mGoogleSignInClient);

    }

}

活動:


protected void onCreate(Bundle savedInstanceState) {

    ...

    mViewModel = new ViewModel(new OnSignInStartedListener() {

        @Override

        public void onSignInStarted(GoogleSignInClient client) {

            startActivityForResult(client.getSignInIntent(), RC_SIGN_IN);

        }

    });

    ...

}


@Override

public void onClick(View v) {

    // Invokes listener this activity created to start sign in flow

    viewModel.loginGoogle();

}

希望有幫助!


查看完整回答
反對 回復 2023-06-08
  • 4 回答
  • 0 關注
  • 250 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號