主页 > 老版本imtoken > 以太坊安卓钱包开发系列之三——资产信息展示

以太坊安卓钱包开发系列之三——资产信息展示

老版本imtoken 2023-01-19 02:24:57

这是关于如何为以太坊开发 Android 钱包系列的第三部分。 显示钱包账户的资产信息。 显示的信息主要包括账户地址、eth余额、账户拥有的Token和余额。

初步知识 MVVM

本文将涉及与UI界面的交互。 提前了解界面和数据如何交互是非常有必要的。 如果您已经熟悉 MVVM,则可以跳过本节。

刚开始写Android的时候,数据和界面经常耦合在一起,一个Activity文件总是很大。 每当改版产品界面,都非常痛苦。 要抱怨,很多产品经理喜欢改界面​​。

后来谷歌推荐了多种架构模式:MPV、MVVM模式解决数据和UI耦合问题,登链钱包代码使用了MVVM模式,所以简单介绍一下,下面是MVVM视图和数据的交互图:

以太坊钱包官方网站_以太坊官方钱包_以太坊中文钱包

View通常对应Activity/Fragment/custom ViewModel:是与数据相关的模块。

View和Model没有直接连接,而是负责接收View层的事件,通过ViewModel获取和处理数据。 ViewModel层的数据变化也会通知View层更新相应的UI,从而实现业务逻辑与Ui的隔离。

使用MVVM模式最大的好处就是解耦,因为数据处理逻辑是独立于View的,当UI发生变化时ViewModel不需要做太多的改动。

我们使用了Google在I/O大会上推出的一套遵循MVVM开发模式的LiveData和ViewModel组件架构。

ViewModel 和 LiveData

ViewModel会关注UI生命周期来存储和管理数据。 当Activity发生变化(锁屏、开屏、旋转)时,ViewModel会自动保留之前的数据,用于新的Activity或Fragment。 当界面被系统销毁时,ViewModel也会进行资源清理,避免内存泄露。

ViewModel 还可以用于不同界面之间的数据共享。

LiveData 是一个可观察的数据持有者类。 Observers可以方便我们异步获取数据,LiveData也是有生命周期感知的。 如果其生命周期处于 STARTED 或 RESUMED 状态。 LiveData 会将观察者视为活跃的,并通知他们数据更改。 未在 LiveData 注册的观察者和不活跃的观察者不会收到更新通知。

要了解更多信息,您可以通过关键字搜索:Lifecycle、ViewModel、LiveData。

账户信息展示

显示的信息主要包括账户地址、eth余额、账户拥有的Token和余额。 界面效果如下:

上图

这个接口应该是登链钱包的PropertyFragment。 上图中的UPT是我自己发行的Token,所以不显示价格。

下面我们来思考一下如何展示上面的数据,不要着急往下看,可以先想一想。

先拆分问题,将数据拆分成4部分:

显示当前选择的账户 显示当前账户的ETH余额 显示当前账户下的Token数量 显示对应的法币金额。

为了避免UI和上面4个数据的耦合,代码中使用了一个TokensViewModel,获取到的数据用LiveData包裹起来,这样UI就可以订阅数据了。 TokensViewModel类如下,删去代码:

public class TokensViewModel extends ViewModel {
    private final MutableLiveData<ETHWallet> defaultWallet;
    private final MutableLiveData<NetworkInfo> defaultNetwork;
    private final MutableLiveData<Token[]> tokens;
    private final MutableLiveData<Ticker> prices;
}

MutableLiveData 是上面提到的 LiveData 的子类。 可以在UI界面订阅数据。 接下来,我们将每一个数据一一拆解。

显示当前帐户

它可以分为两个步骤:

从数据库中读取账号; 界面显示账号

TokensViewModel中定义了一个MutableLiveData<ETHWallet> defaultWallet,将从数据库读取的账号存储到defaultWallet中,然后UI会观察并显示defaultWallet。

注意:该方式在登链钱包中被广泛使用,使用了一个LiveData作为数据桥梁。

在上一篇导入账户和账户管理中,所有的账户都是使用greenDao存储的,所以我们只需要从中加载所有账户,选择当前选中的即可。 看一下代码:

    public static ETHWallet getCurrent() {
        List<ETHWallet> ethWallets = ethWalletDao.loadAll();
        for (ETHWallet ethwallet : ethWallets) {
            if (ethwallet.isCurrent()) {
                ethwallet.setCurrent(true);
                return ethwallet;
            }
        }
        return null;
    }

上述代码使用 ETHWalletDao.loadAll 先加载所有账户,并返回当前选择的账户。 上面的代码将被 FetchWalletInteract 类的 findDefault 方法调用。 在ViewModle中以太坊官方钱包,很多情况下与数据进行交互的类都会被命名为xxxInteract。 也是成语。

其代码如下:

   // 返回一个可订阅的Single<ETHWallet> 对象
   public Single<ETHWallet> findDefault() {
        return Single.fromCallable(() -> {
            return WalletDaoUtils.getCurrent();
        }).subscribe(this::onDefaultWallet);
    } 
    // 获取到默认钱包账号 设置到 defaultWallet 这个LiveData
    private void onDefaultWallet(ETHWallet wallet) {
        defaultWallet.setValue(wallet);
    }

findDefault() 返回一个可订阅的 Single 对象,如果您不熟悉,请参考以下文档。

之后,在UI界面PropertyFragment.java中,可以订阅defaultWallet:

tokensViewModel.defaultWallet().observe(this,  this::showWallet);

当获取到默认账户后以太坊官方钱包,会回调showWallet:

// UI 显示
    public void showWallet(ETHWallet wallet) {
        tvWalletName.setText(wallet.getName());
        tvWalletAddress.setText(wallet.getAddress());
    }

这样,界面的展示就完成了,下一篇继续介绍余额的获取。

参考文档生命周期官方文档地址RxAndroid了解更多响应式编程