mardi 25 août 2020

Android Where to start Activity in MVVM Resarlt

I supposed to use MVVM pattern with Data Repository. Data Came from Web Api call. and based on The Data, The Application Start The Web Browser With Returned URL.

  1. on user interaction The Activity calls ViewModel Which owns Data:

CheckOutActivity.java:

MaterialRippleLayout makeOrder = findViewById(R.id.btn_make_order);
    makeOrder.setOnClickListener(view ->{
        viewModel.makeOrder();
    });
  1. viewModel calls DataRepository with Appropriate Data (optionalShippingEntityIds) to call Web Api Async:

CheckOutViewModel.java

public void makeOrder(){
    cartRepository.makeOrder(optionalShippingEntityIds.getValue());
}

The Repository has been instantiated before:

public CheckOutViewModel(@NonNull Application application) {
    super(application);
    cartRepository = new CartRepository(application);
}  
  1. in DataRepository Api Call performs:

CartRepository

public void makeOrder(ArrayList<Integer> optionalShippingEntityIds){
    HashMap<String,String> map = new HashMap<String,String>();
    String  idsString=optionalShippingEntityIds.toString();
    map.put("shipment_saleitem_id",idsString);
    rest.httpRequest(RestAdapter.HttpVerb.POST,"order",map,new makeOrderHandler());
}

The CartRepository Constructor:

private RestAdapter rest;
private Context context;

public CartRepository(Context context) {
    this.context = context;
    rest = RestAdapter.getInstance(context);
    version.setValue(0);
}

4.HttpResponseHandler Handle The Web Browser open URL or Toast fail message

CartRepository.java

class makeOrderHandler extends JsonHttpResponseHandler{
    @Override
    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
        if(statusCode == 200){
            try {
                Toast.makeText(context,"order number "+response.getInt("order_id")+"has been created",Toast.LENGTH_SHORT).show();
                String redirectUrl = response.getString("init_payment_url");
                version.setValue(version.getValue() +1);

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(redirectUrl));
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        context.startActivity(intent);
                        ((Activity)context).finishAffinity();
                        //System.exit(0);

                        /*Intent chooserIntent = Intent.createChooser(intent, "Open With");
                        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(chooserIntent);*/
                    }
                }, 2000);
            } catch (JSONException e) {
                Toast.makeText(context,"JSON parse error"+" : "+response.toString(), Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
        }else{
            Log.e("server api changed ", "error in getting response using known api \n" + response.toString());
            Toast.makeText(context,"api change",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, String res, Throwable t) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
        Log.e("server 500", "error in getting response using async-apache-http call"+" : "+res);
        t.printStackTrace();
        Toast.makeText(context, "خطا سرور ", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, Throwable t, JSONObject e) {
        if(statusCode == 504){
            Toast.makeText(context,"The Order hasnt been created duo to internal problem. please try again",Toast.LENGTH_SHORT).show();
        }else{
            Log.e("server api changed", "error in getting response using known api \n" + e.toString());
            t.printStackTrace();
            Toast.makeText(context,"Api is unknown",Toast.LENGTH_SHORT).show();
        }
    }
}

The Problem is after i launch The Application in some Devices, in The Line ((Activity)context).finishAffinity(); The Application Crashes because The context is an application context instance and not an activity context instance .

  • if i pass The Activity instance Through ViewModel, i had just violated The MVVM.
  • if i make an interface in The Activity and implement it. it violates The Activity Single Responsibility (Data Repository Response Handler Should Handle The startActivity)
    so i dont know how to handle this perfectly.
  • if i eliminate The ViewModel makeOrder, and Construct The Repository With The Activity Context I think its ViewModel Responsibility to Handle The Data Manipulation Job.

....

So I am Confused With The Right Solution To Handling StartActivity and Toast in Response.

if anyone could help me With The Right Design Pattern i Would Appreciate.

Aucun commentaire:

Enregistrer un commentaire