首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android应用程序架构--我做得对吗?

Android应用程序架构--我做得对吗?
EN

Stack Overflow用户
提问于 2020-03-08 12:54:21
回答 2查看 70关注 0票数 2

我在这里遵循这个指南,https://developer.android.com/jetpack/docs/guide?hl=en

为了学习关注点的分离,我创建了一个简单的应用程序,它从API中获取一些数据并在活动中显示在屏幕上。

我的活动如下,其职责是向用户显示信息。

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button myButt;
    private MainViewModel mvw;
    private TextView myView;
    private MutableLiveData<Orders> mld;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mvw = new ViewModelProvider(this).get(MainViewModel.class);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myButt = findViewById(R.id.button);
        myView = findViewById(R.id.textview);
        myButt.setOnClickListener(this);

        mvw.getMld().observe(this, new Observer<Orders>() {
            @Override
            public void onChanged(Orders orders) {
                Log.i("livedata","got an updt");
                myView.setText(mvw.extractDate(orders));
            }
        });
    }

    @Override
    public void onClick(View view) {
        switch(view.getId()){
            case R.id.button:
                Log.i("tag","hello");
                mvw.updateData();
        }
    }
}

下面遵循ViewModel,它关心的是从存储库类中获取数据,并在活动中显示数据之前对这些数据进行一些计算。

代码语言:javascript
复制
public class MainViewModel extends ViewModel {
    private GetOrder getOrderRepo;
    private MutableLiveData<Orders> mld;

    public MainViewModel(){
        getOrderRepo = new GetOrder();
        mld = getOrderRepo.getAllOrders();
    }

    public MutableLiveData<Orders> getMld() {
        return mld;
    }

    public void setMld(MutableLiveData<Orders> mld) {
        this.mld = mld;
    }





    public void updateData(){
        getOrderRepo.getAllOrders(); //discard the return value
    }

    public String extractDate(Orders orders){
        ArrayList<Order> listOfOrders = orders.getOrders();
        String date = listOfOrders.get(0).getOrderTime();
        return date;
    }

}

接下来是存储库,它处理来自API的GET请求,并将其放入MutableLiveData容器"allOrders“中。

代码语言:javascript
复制
public class GetOrder {
    private ApiService mAPIService;
    MutableLiveData<Orders> allOrders;
    private Orders orders;
    public GetOrder(){
        mAPIService = ApiUtils.getAPIService();
    }
    public MutableLiveData<Orders> getAllOrders(){
        Log.i("func","starting func");
        allOrders = new MutableLiveData<Orders>();
        mAPIService.getOrders().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Orders>() {
                    @Override
                    public void onCompleted() {
                        Log.i("func","onComplete");

                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("onError",e.toString());

                    }

                    @Override
                    public void onNext(Orders orders) {
                        Log.i("Repo",orders.toString());
                        allOrders.setValue(orders);
                    }
                });
        return allOrders;
    }
}

这是一个正确的实现吗?还是我误解了什么?

我需要考虑的一个问题是按钮具有mvw.orderData().observe(这个,新的观察者()),因为这每次都会创建一个新的观察者。还是在每个onChanged之后就死了?

反馈后更新

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-08 13:24:18

您在这里实现的是MVVM架构。模型(存储库)-View(活动)-VM(视图模型)。基本结构看起来不错,但我看到了一些可以改进的地方,以便更好地遵循最佳实践。

  1. 正如您所说的,您正在为每个按钮单击创建一个新的观察者。您应该在onCreate中观察onCreate。在ViewModel中添加一个函数,告诉存储库更新数据,并在onClick方法中调用它。
  2. 您应该将MutableLiveData实现为私有,并将其包装到LiveData中,然后在活动中观察。所以它不受变异的影响。另外,ViewModel应该存储获取的MutableLiveData。

更新(2):检查此链接下的MainActivityViewModel。您在MutableLiveData中设置的ViewModel应该是私有的。

代码语言:javascript
复制
 private MutableLiveData<List<String>> fruitList;

然后通过普通的MutableLiveData返回该LiveData。这个LiveData是不可变的,不能是空的,因此可以安全地向您的MainActivity这样的类公开,在那里您可以观察到它。

代码语言:javascript
复制
LiveData<List<String>> getFruitList() {
        if (fruitList == null) {
            fruitList = new MutableLiveData<>();
            loadFruits();
        }
        return fruitList;
    } 

在您的示例中,loadFruits()函数将是存储库中的api调用。

  1. 您应该使用ViewModel和/或ViewModelFactory实例化ViewModelProvider。这里是一个更详细的解释。它应该是这样的: 私有val viewModel =viewModel

现在它已经意识到生命周期了。如果您愿意的话,以后可以在片段中插入相同的实例。

  1. 只是为了好玩:我喜欢您的按钮变量如何被称为myButt :D
票数 1
EN

Stack Overflow用户

发布于 2020-03-08 13:10:59

ViewModel应该负责数据的存储。

因此,更好的方法是将MutableLiveData<Orders> allOrders;放在ViewModel中而不是存储库中。这样,Repository只负责获取数据。它不应该储存它。

然后,在您的活动中,您应该观察allOrders实时数据,如:mvw.allOrders.observe(...) in onCreate()

在单击按钮时,只需调用Repository方法,使用ViewModel的方法allOrders LiveData获取/更新orderData()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60587662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档