网络等待提示框......

前言

近期在做项目的时候遇到这样一个需求:在网络情况不好的时候需要提醒用户当前网络状况不佳,又或者网络不好的时候请求服务器超时,需要提醒用户,并再次做处理。

首先说一下我是怎么从服务器拿数据的;

public static String readStream(InputStream is) {
        InputStreamReader isr;
        String result = "";
        try {
            String line = "";
            isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            while ((line = br.readLine()) != null) {
                result += line;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;

    }

     public static ArrayList<AppInfo> getJsonData(String url) {
        ArrayList<AppInfo> appInfoList = new ArrayList<AppInfo>();
        String jsonString =readStream(new URL(url).openStream());
        JSONObject jsonObject;
        AppInfo appInfo;
        try {
            jsonObject = new JSONObject(jsonString);
            JSONArray jsonArray = jsonObject.getJSONArray("message");
            for (int i = 0; i < jsonArray.length(); i++) {
                jsonObject = jsonArray.getJSONObject(i);
                appInfo = new AppInfo();
                appInfo.appName = jsonObject.getString("appName");
                appInfo.appIconUrl = jsonObject.getString("iconUrl");
                appInfo.appSize = jsonObject.getString("appSize");
                appInfo.appDownloadUrl = jsonObject.getString("apkUrl");
                appInfo.appVersionName = jsonObject.getString("version");
                appInfo.packageName = jsonObject.getString("packageName");
                appInfo.install = jsonObject.getString("validStatus");
                appInfo.appVersionCode = jsonObject.getString("versionCode");
                appInfoList.add(appInfo);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return appInfoList;
    }

 class NewsAsyncTask extends AsyncTask<String, Void, List<Bean>> {

        @Override
        protected List<Bean> doInBackground(String... params) {
            return getJsonData(params[0]);
        }

        @Override
        protected void onPostExecute(List<Bean> beans) {
            super.onPostExecute(beans);
            if (beans.size() != 0 ) {
                adapter = new MyAdapter(HomePage.this, beans);
                listView.setAdapter(adapter);
            } else {
                //我的处理
            }
        }
    }

为什么直接用readStream(new URL(url).openStream()),而不是用HttpUrlConnection?其实这个就是对HttpUrlConnection的封装。

public final InputStream openStream() throws IOException {
   return openConnection().getInputStream();
}

面对突然起来的改动,我盲目了,为什么?大家都知道如果用httpurlconnection对数据进行请求的话,有这样两个方法:

  connection.setReadTimeout();
  connection.setConnectTimeout();

分别是对从主机读取数据超时和对连接服务器超时的设置,如果我还是用封装的方法进行请求的话,根本找不到这两个方法,于是我只能改掉我的核心部分,其实也没多少代码量。

改完的部分代码:

 public static ArrayList<AppInfo> getJsonData() {
        ArrayList<AppInfo> appInfoList = new ArrayList<AppInfo>();
        String jsonString = getURLResponse();
        JSONObject jsonObject;
        AppInfo appInfo;
        try {
            jsonObject = new JSONObject(jsonString);
            JSONArray jsonArray = jsonObject.getJSONArray("message");
            for (int i = 0; i < jsonArray.length(); i++) {
                jsonObject = jsonArray.getJSONObject(i);
                appInfo = new AppInfo();
                appInfo.appName = jsonObject.getString("appName");
                appInfo.appIconUrl = jsonObject.getString("iconUrl");
                appInfo.appSize = jsonObject.getString("appSize");
                appInfo.appDownloadUrl = jsonObject.getString("apkUrl");
                appInfo.appVersionName = jsonObject.getString("version");
                appInfo.packageName = jsonObject.getString("packageName");
                appInfo.install = jsonObject.getString("validStatus");
                appInfo.appVersionCode = jsonObject.getString("versionCode");
                appInfoList.add(appInfo);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return appInfoList;
    }

  private static String getURLResponse() {
        HttpURLConnection conn = null; //连接对象
        InputStream is = null;
        String resultData = "";
        Message msg = new Message();
        try {
            URL url = new URL(HttpApi.URL_MAIN); //URL对象
            conn = (HttpURLConnection) url.openConnection(); //使用URL打开一个链接
            conn.setReadTimeout(6000);
            conn.setConnectTimeout(6000);
            conn.setRequestMethod("POST"); //使用POST请求
            is = conn.getInputStream();   //获取输入流,此时才真正建立链接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine = "";
            while ((inputLine = bufferReader.readLine()) != null) {
                resultData += inputLine + "\n";
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ConnectException e) {

        } catch (SocketTimeoutException e) {

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return resultData;
    }

改完之后,下面就可以考虑如何对超时问题进行一个异常捕获并作处理了;当你给请求设置setReadTimeout()和setConnectTimeout()方法之后,可以手动的添加异常ConnectExceptionSocketTimeoutException,对于这两个异常,我刚开始也感到很陌生,感觉都一样都是连接超时异常嘛!其实不然,可以看一下下面这篇文章(https://www.zhihu.com/question/29749015),我自己理解为请求建立超时异常和建立完成数据返回超时异常。有了这两个异常就好办多了,既然有异常了,那么我就可以才对应的异常中做处理了呀!小白博主不管这两个异常是什么,我都只要告诉用户当这两个异常有任何一个发生时都是网络不好(大家不要向我这么做,我这是项目要求这么做的,还是得具体问题具体对待)。

好,下面开始开心地处理异常了,不就是弹个吐司告诉用户嘛,简单!

catch (ConnectException e) {
    Toast.makeText(mContext,"网络不佳,请重试",LENGTH_SHORT).show();
 } catch (SocketTimeoutException e) {
    Toast.makeText(mContext,"网络不佳,请重试",LENGTH_SHORT).show();
 } 

运行一下看看吧,我擦勒…崩溃了….想必什么原因大家也都知道了,啊哈…这就是小白博主啊,子线程中不能更新UI啊啊啊啊啊!!!(反思一会……),知道原因就好改多了,既然子线程不允许,那我回主线程更新好了呀!那么问题来了,这是一个类怎么创建Handler并发送回主Activity呢?想来想去只有在调用方法中传参了(有人告知类中怎么创建Handler吗?),最后更新都是回到Activity中,获取网络数据的方法也是在Activity中调用的,那就可以在Activity中把Handler对象传递到网络获取的方法中呀! (有点意思了),再次改动代码:

  private static String getURLResponse(Handler handler) {
        HttpURLConnection conn = null; //连接对象
        InputStream is = null;
        String resultData = "";
        Message msg = new Message();
        try {
            URL url = new URL(HttpApi.URL_MAIN); //URL对象
            conn = (HttpURLConnection) url.openConnection(); //使用URL打开一个链接
            conn.setReadTimeout(6000);
            conn.setConnectTimeout(6000);
            conn.setRequestMethod("POST"); //使用post请求
            is = conn.getInputStream();   //获取输入流,此时才真正建立链接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine = "";
            while ((inputLine = bufferReader.readLine()) != null) {
                resultData += inputLine + "\n";
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ConnectException e) {
            msg.what = 8;
            handler.sendMessage(msg);
        } catch (SocketTimeoutException e) {
            msg.what = 8;
            handler.sendMessage(msg);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }

        return resultData;
    }


  public static ArrayList<AppInfo> getJsonData(Handler handler) {
        ArrayList<AppInfo> appInfoList = new ArrayList<AppInfo>();
        String jsonString = getURLResponse(handler);
        JSONObject jsonObject;
        AppInfo appInfo;
        try {
            jsonObject = new JSONObject(jsonString);
            JSONArray jsonArray = jsonObject.getJSONArray("message");
            for (int i = 0; i < jsonArray.length(); i++) {
                jsonObject = jsonArray.getJSONObject(i);
                appInfo = new AppInfo();
                appInfo.appName = jsonObject.getString("appName");
                appInfo.appIconUrl = jsonObject.getString("iconUrl");
                appInfo.appSize = jsonObject.getString("appSize");
                appInfo.appDownloadUrl = jsonObject.getString("apkUrl");
                appInfo.appVersionName = jsonObject.getString("version");
                appInfo.packageName = jsonObject.getString("packageName");
                appInfo.install = jsonObject.getString("validStatus");
                appInfo.appVersionCode = jsonObject.getString("versionCode");
                appInfoList.add(appInfo);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return appInfoList;
    }

 class NewsAsyncTask extends AsyncTask<String, Void, List<AppInfo>> {

        @Override
        protected List<AppInfo> doInBackground(String... params) {
            return HttpUtils.getJsonData(handler);
        }

        @Override
        protected void onPostExecute(List<AppInfo> beans) {
            super.onPostExecute(beans);
            if (beans.size() != 0) {
               //我的处理
                }
                appAdapter = new AppAdapter(getActivity(), beans);
                listView.setAdapter(appAdapter);
            } else {
            }
        }
    }

主Activity中AsyncTask请求网络,通过调用getJsonData()方法来得到封装好的网络实体,在获取网络数据的方法和封装网络数据的方法中分别传入handler对象。

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 8) {
               Toast.makeText(this, "网络状态不佳,请稍后重试", Toast.LENGTH_SHORT).show();
                proDialog.dismiss();
            }
        }
    };

最后在主线程中就可以做任意操作了。别忘记添加网络权限了………

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值