[ 转载]Android by example : MVVM +Data Binding -> Model (Part 2)

原文:https://medium.com/@husayn.hakeem/android-by-example-mvvm-data-binding-model-part-2-82b5e3ee6ccb
This article is part 4/4 from a series or articles about implementing the MVVM design pattern and data binding in a sample Tic-Tac-Toe application. If you’re unfamiliar with the terms data binding or MVVM pattern, refer to part 1 for a quick refresher. In part 2 we implement the Model classes, while in part 3 we implement the View Model class, so make sure to read through them before continuing along this part.

Note: You’ll find all the code for this project in the following Github repo.

husaynhakeem/TicTacToe-MVVM

TicTacToe-MVVM - Sample android application used to learn the Model View View Model pattern and DataBinding in Android
github.com
V for View
Let’s start by the XML code. This following file is named activity_game.xml.

<?xml version="1.0" encoding="utf-8"?>

<data>

    <variable
        name="gameViewModel"
        type="husaynhakeem.io.tictactoe_mvvm.viewmodel.GameViewModel" />
</data>

<android.support.v7.widget.GridLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:padding="32dp">

    <TextView
        android:id="@+id/cell_00"
        style="@style/CellTextView"
        android:background="@drawable/cell_00"
        android:onClick="@{() -> gameViewModel.onClickedCellAt(0, 0)}"
        android:text='@{gameViewModel.cells["00"]}'
        app:layout_column="1"
        app:layout_columnWeight="1"
        app:layout_row="1"
        app:layout_rowWeight="1" />
    ...
</android.support.v7.widget.GridLayout>
2 things to note about the code above

You’ll notice that the rest of the cells (TextViews) were ommitted, they all resemble the one present above, each calling the onClickedCell method from the ViewModel once clicked upon, and each displaying the value of the variable cells from the View Model class.
A variable of the name gameViewModel of type GameViewModel is used in the layout above, its value is set in the GameActivity class as you’ll see shortly.
This is it for the layout, let’s now see the GameActivity class.

As we said in part 3, the View will observe for the end of the game, which is indicated by aLiveData instance provided by the ViewModel.

Here is a list of things the View should be able to do:

Prompt the players to enter their names. A Tic-Tac-Toe game is played by 2 players, their names are required before begining a game.
Subscribe and bind to the View Model’s LiveData.
React to notifications from the View Model
The code below is the implementation of the main View class, it implements each of the requirements written above.

public class GameActivity extends AppCompatActivity {

private static final String GAME_BEGIN_DIALOG_TAG = "game_dialog_tag";
private static final String GAME_END_DIALOG_TAG = "game_end_dialog_tag";
private static final String NO_WINNER = "No one";
private GameViewModel gameViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    promptForPlayers();
}

public void promptForPlayers() {
    GameBeginDialog dialog = GameBeginDialog.newInstance(this);
    dialog.show(getSupportFragmentManager(), GAME_BEGIN_DIALOG_TAG);
}

public void onPlayersSet(String player1, String player2) {
    initDataBinding(player1, player2);
}

private void initDataBinding(String player1, String player2) {
    ActivityGameBinding activityGameBinding = DataBindingUtil.setContentView(this, R.layout.activity_game);
    gameViewModel = ViewModelProviders.of(this).get(GameViewModel.class);
    gameViewModel.init(player1, player2);
    activityGameBinding.setGameViewModel(gameViewModel);
    setUpOnGameEndListener();
}

private void setUpOnGameEndListener() {
    gameViewModel.getWinner().observe(this, this::onGameWinnerChanged);
}

@VisibleForTesting
public void onGameWinnerChanged(Player winner) {
    String winnerName = winner == null || isNullOrEmpty(winner.name) ? NO_WINNER : winner.name;
    GameEndDialog dialog = GameEndDialog.newInstance(this, winnerName);
    dialog.show(getSupportFragmentManager(), GAME_END_DIALOG_TAG);
}

}
Things to note about the code:

gameViewModel.getWinner().observe(…): This method observes the winner LiveData instance. When the end of the gale is reached, the winner’s value is changed which triggers the onGameWinnerChanged method.
ActivityGameBinding: This class is generated based on the XML layout file activity_game.xml. This class holds all the bindings from the layout properties (in our case, we only have the gameViewModel variable from the XML layout). This class also knows how to assign values for the binding expressions, which brings us to the next point.
setGameViewModel: Method that assigns a value to the gameViewModel variable from the XML layout file.
You’ll notice that in the code, 2 dialog classes are being used, in order to keep the article concise and only focus on the important parts of the implementation, their codes hasn’t been added to this article, but rest assured, their code has nothing new to them, you’ll find them in the code in the Github repo for this project.
Congrats if you’ve made it this far! Hopefully by now you’ll have a better understanding of the MVVM pattern, and how to use data binding.

Feel free to ask questions, your remarks are also welcome.

Thanks for reading this article. Be sure to like and recommend it if you found it helpful.

For more about Java and Android, follow me so that you’ll get notified when I write new posts, or connect with me here on Github and Linkedin.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值