显示“无法访问网络”的有效方式使用“重试”和“Wifi 设置”、“移动网络”等附加选项查看

Posted

技术标签:

【中文标题】显示“无法访问网络”的有效方式使用“重试”和“Wifi 设置”、“移动网络”等附加选项查看【英文标题】:Efiicient way to show 'Cant access network' View with 'Retry' and additional options like 'Wifi Settings', 'Mobile Network' 【发布时间】:2016-01-17 15:39:05 【问题描述】:

我需要将其包含在我的应用中

什么时候触发?

用户从 UI 触发的任何操作都需要互联网并且没有互联网 任何需要互联网的后台活动(如异步加载图像)都没有互联网 当应用程序处于空闲状态或正在处理需要互联网的后台/用户操作时

我尝试了什么?

    我使用 Volley。在 Volley 的Response.ErrorListener 内触发AlertDialog,每次我写一个JsonObjectRequest

问题:过于重复,AlertDialog 代码行数过多

    添加了一个名为Alerts 的通用类,并从中调用AlertDialog

    DialogInterface.OnClickListener onClickTryAgain = new DialogInterface.OnClickListener() 
        @Override
        public void onClick(DialogInterface dialog, int which) 
            Swift.getInstance(ProfileActivity.this).addToRequestQueue(jsonObjectRequest);
        
    ;
    if(error instanceof TimeoutError) Alerts.timeoutErrorAlert(ProfileActivity.this, onClickTryAgain);
    else if(error instanceof NoConnectionError) Alerts.internetConnectionErrorAlert(ProfileActivity.this, onClickTryAgain);
            else Alerts.unknownErrorAlert(ProfileActivity.this);
    

我的 Alerts.class

    public class Alerts 


        public static void internetConnectionErrorAlert(final Context context, DialogInterface.OnClickListener onClickTryAgainButton) 
            String message = "Sometimes the internet gets a bit sleepy and takes a nap. Make sure its up and running then we'll give it another go";
            new AlertDialog.Builder(context)
                    .setIconAttribute(android.R.attr.alertDialogIcon)
                    .setTitle("Network Error")
                    .setMessage(message)
                    .setPositiveButton("Try Again", onClickTryAgainButton)
                    .setNegativeButton("Turn Internet On", new DialogInterface.OnClickListener() 
                        @Override
                        public void onClick(DialogInterface dialog, int which) 
                            Intent i = new Intent(Settings.ACTION_SETTINGS);
                            ((Activity) context).startActivityForResult(i, 0);
                        
                    )
                    .show();
        

        public static void timeoutErrorAlert(Context context, DialogInterface.OnClickListener onClickTryAgainButton) 
            String message = "Are you connected to internet? We guess you aren't. Turn it on and we'll rock and roll!";
            new AlertDialog.Builder(context)
                    .setIconAttribute(android.R.attr.alertDialogIcon)
                    .setTitle("Network Error")
                    .setMessage(message)
                    .setPositiveButton("Try Again", onClickTryAgainButton)
                    .show();
        

        public static void unknownErrorAlert(Context context) 
            new AlertDialog.Builder(context)
                    .setIconAttribute(android.R.attr.alertDialogIcon)
                    .setTitle("Server Error")
                    .setMessage("We all have bad days! We'll fix this soon...")
                    .setPositiveButton("Hmm, I understand", new DialogInterface.OnClickListener() 
                        @Override
                        public void onClick(DialogInterface dialog, int which) 
                        
                    )
                    .show();
        
    

问题Try again 按钮不符合我的要求。好吧,假设有人对此进行了修复,我可以说,它只是用 5 行代码替换了大约 30 行代码,但是过渡呢?我需要说connecting,直到响应到达

    这一次,我添加了一个名为 ConnectingLayout 的布局,覆盖了整个屏幕。

    <LinearLayout
        android:orientation="vertical"
        android:layout_
        android:layout_
        android:gravity="center_vertical|center_horizontal"
        android:id="@+id/loading_layout"
        android:visibility="gone">
    
        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_
            android:layout_
            android:indeterminate="true" />
    
        <TextView
            android:layout_
            android:layout_
            android:text="@string/loading"
            android:gravity="center_horizontal"
            android:textSize="25sp"
            android:fontFamily="sans-serif-light"
            android:layout_margin="5dp"
            android:singleLine="true" />
    
        <TextView
            android:layout_
            android:layout_
            android:text="@string/loading_description"
            android:gravity="center_horizontal"
            android:fontFamily="sans-serif-light"
            android:layout_margin="5dp"
            android:singleLine="true" />
    </LinearLayout>
    

并像在中一样使用它

    jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, getString(R.string.api_root_path) + "/profile", getJson(), new Response.Listener<JSONObject>() 
        @Override
        public void onResponse(JSONObject response) 
            try 
                if(response.getBoolean("success")) 
                    Animations.fadeOut(loadingLayout,500);
                    Animations.fadeIn(mainLayout,500);
                    JSONObject dataJson = response.getJSONObject("data");
                    JSONObject userJson = dataJson.getJSONObject("user");
                    name.setText(userJson.getString("name"));
                    dob.setText(userJson.getString("dob").equals("null")?null:userJson.getString("dob"));
                    email.setText(userJson.getString("email"));
                    phone.setText(userJson.getString("mobile_no"));
                    promotionOffers.setChecked(userJson.getBoolean("offers"));
                 else 
                    Alerts.requestUnauthorisedAlert(ProfileActivity.this);
                    System.out.println(response.getString("error"));
                
             catch (JSONException e)  e.printStackTrace(); 
        
    , new Response.ErrorListener() 
        @Override
        public void onErrorResponse(VolleyError error) 
            DialogInterface.OnClickListener onClickTryAgain = new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialog, int which) 
                    VolleyBaseClass.getInstance(ProfileActivity.this).addToRequestQueue(jsonObjectRequest);
                
            ;
            if(error instanceof TimeoutError) Alerts.timeoutErrorAlert(ProfileActivity.this, onClickTryAgain);
            else if(error instanceof NoConnectionError) Alerts.internetConnectionErrorAlert(ProfileActivity.this, onClickTryAgain);
            else Alerts.unknownErrorAlert(ProfileActivity.this);
            System.out.println("Response Error: " + error);
        
    );
    Animations.fadeIn(loadingLayout, 500);
    Animations.fadeOut(mainLayout, 500);
    VolleyBaseClass.getInstance(this).addToRequestQueue(jsonObjectRequest);

假设 Animations.fadeIn(View view, int ms);Animations.fadeOut(View view, int ms); 已正确定义并完成工作。

问题:在所有活动中重复布局和编写代码淡化的痛苦

    了解ViewStubs。以编程方式生成代码以获得相同的ConnectingLayout。现在我可以更改文本,例如保存、加载等。

问题:不是很大的飞跃,但是... ..,这是我刚刚踏上的又一块垫脚石

    我不需要说它的连接或加载,我只需要说'嘿,你的手机正在处理一些东西'。所以我只是想为什么不使用SwipeRefreshLayouts 中的加载圈呢?

问题:太好了,顶部显示的加载圆形缺口很小,如果加载失败,我可以调用警报,但是在哪里打开 wifi,打开 3G和其他东西,对于AlertDialog 来说太大而无法容纳所有这些,有没有其他方法可以显示try again

    考虑使用same fragment in all activitiesredirecting to a callActivityForResult(抱歉我不能添加两个以上的链接)

问题:嗯……!我发现将用户带入一项新活动会消耗资源并大大降低性能。还有碎片?

我不会放弃!我知道我正在努力学习它,但我非常希望开发者社区能够帮助我。

【问题讨论】:

【参考方案1】:

Volley 在从服务器接收到某些内容时DETROYS all listeners,无论响应是正确响应还是错误响应。

每次发送或重新发送请求时都需要构造它。

这些步骤将有助于实现它

使用Retry 和其他必要按钮(如Wifi SettingsMobile Network Settings)创建片段 在必要的视图上在RelativeLayout 内创建一个全尺寸的FrameLayout以容纳创建的片段并最初隐藏它 请求失败时,使FrameLayout可见,重试按钮应该调用构造和调用请求的函数

【讨论】:

【参考方案2】:

我也遇到过同样的需求和问题。我正在开发一个基于 Volley 的库 jus,我使用 rxJava 全局 observables 处理您遇到的大多数问题,当然还有带有静态警报/视图生成器的 Alerts 类。连接处理我尝试使用ConnectivityManager 和NoConnectionPolicy 概念使其平滑。

【讨论】:

以上是关于显示“无法访问网络”的有效方式使用“重试”和“Wifi 设置”、“移动网络”等附加选项查看的主要内容,如果未能解决你的问题,请参考以下文章

修改有效载荷的 Alamofire 重试请求

可达性 - 检查公共 Wi-Fi 连接是不是有效

使用 C# 连接/重试连接的最有效方法?

安装AUTO CAD2007时 出现 “错误1606无法访问网络位置Autodesk\autocad2007\R17.1\chs\”的报错 怎么解决

有没有办法监控内部 Azure 数据工厂管道,例如有效负载大小、重试次数、并发作业和类似参数?

如何使自定义子命令自动重试