GithubHelp home page GithubHelp logo

codes-notes-and-tips's People

Contributors

shinelikeamillion avatar

Watchers

 avatar

Forkers

yuantang

codes-notes-and-tips's Issues

This Handler class should be static or leaks might occur

Repost from: http://blog.csdn.net/wuleihenbang/article/details/17126371

This Handler class should be static or leaks might occur
Handler类应该定义成静态类,否则可能导致内存泄露。

Issue: Ensures that Handler classes do not hold on to a reference to an outer class

In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread's MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

大体翻译如下:
Handler 类应该应该为static类型,否则有可能造成泄露。
在程序消息队列中排队的消息保持了对目标Handler类的应用。如果Handler是个内部类,那 么它也会保持它所在的外部类的引用。为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。

To deal with it:

static class MyHandler extends Handler {  
                WeakReference<PopupActivity> mActivity;  

                MyHandler(PopupActivity activity) {  
                        mActivity = new WeakReference<PopupActivity>(activity);  
                }  

                @Override  
                public void handleMessage(Message msg) {  
                        PopupActivity theActivity = mActivity.get();  
                        switch (msg.what) {  
                        case 0:  
                                theActivity.popPlay.setChecked(true);  
                                break;  
                        }  
                }  
 }  

开启多线程从测速服务器下载数据实现测速

开启多线程下载,每秒统计一次速率,多线程更新UI

package com.woapp.mainhome.pages;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.woapp.R;
import com.woapp.framework.conn.CmdTask;
import com.woapp.framework.conn.CmdTask.CmdCallBack;
import com.woapp.testSpeed.AboutSpeedTestActivity;
import com.woapp.testSpeed.TestGameSpeedActivity;
import com.woapp.testSpeed.TestSiteSpeedActivity;
import com.woapp.testSpeed.TestVideoSpeedActivity;
import com.woapp.testSpeed.service.TestSpeedServ;

public class SpeedTestPage extends AbsPages implements OnClickListener,CmdCallBack{
    private Button btn_start_test;
    private TextView tv_test_site, 
                     tv_test_video, 
                     tv_test_game, 
                     tv_about_speed_test,
                     tv_speed,
                     tv_test_speed_hint;

    private ImageView iv_hand_of_dial;

    private static final int UPDATE_SPEED_REAL_TIME = 0X001;
    private static final int SPEED_TEST_FINISH = 0X002;

    private static double max_speed;
    private boolean isHandRotating = false;
    private List<String> testIpList = new ArrayList<String>();

    private Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.rotate_animation);

    private List<String> list = new ArrayList<String>();
    private double allThreadDownloadLength;
    private int timeStamp = 1;

    private Timer timer;
    private MyTask myTask;
    private class MyTask extends TimerTask {
        String speed = null;
        double speedD;
        @Override
        public void run() {
            if (allThreadDownloadLength > 0) {
                if (timeStamp <= 5) {
                    speedD = allThreadDownloadLength / timeStamp;
                    speed = transSpeed(speedD);
                    sendMessage(UPDATE_SPEED_REAL_TIME, speed);
                }
                else if (timeStamp > 5 && timeStamp <= 15) {
                    speedD = allThreadDownloadLength / (timeStamp - 5);
                    speed = transSpeed(speedD);
                    sendMessage(UPDATE_SPEED_REAL_TIME, speed);
                    getMaxspeed(speedD);
                }
                else {
                    isHandRotating = false;
                    sendMessage(SPEED_TEST_FINISH, transSpeed(max_speed));
                }
                //计时器到5秒时清零
                if (timeStamp == 5) {
                    allThreadDownloadLength = 0;
                }
                timeStamp++;
            }
        }
    }

    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String speed = msg.getData().getString("speed");
            System.err.println(msg.what);

            switch (msg.what) {
            case UPDATE_SPEED_REAL_TIME:{
                tv_speed.setText(Html.fromHtml(speed));
                break;
            }
            case SPEED_TEST_FINISH:{
                speedTestFinish(speed);
                break;
            }
            default:{
                break;
            }
            }
        };
    };

    public void speedTestFinish (String speed) {
        tv_speed.setText(Html.fromHtml(speed));
        if (isHandRotating == false) {
            startRotatingOrNot(isHandRotating);
            if (timer != null) {
                timer.cancel();
                timer = null;
            } 
            if (myTask != null) {
                myTask.cancel();
                myTask = null;
            }
            btn_start_test.setText("开始测速");
            tv_test_speed_hint.setText("网速受到网络环境影响,建议测速前关闭其他网络应用,\n并避免其它终端使用宽带.");
            //结束的时候还原数据
            max_speed = 0;
            timeStamp = 1;
            allThreadDownloadLength = 0;
        }
    }

    public SpeedTestPage(Context context) {
        super(context);
    }


    @Override
    public boolean msgArrival(int msgId, Object msgData) {
        return false;
    }

    @Override
    protected void initView() {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        inflater.inflate(R.layout.speed_test_page, this);

        btn_start_test = (Button) findViewById(R.id.btn_start_test);
        tv_test_site = (TextView) findViewById(R.id.tv_test_site);
        tv_test_video = (TextView) findViewById(R.id.tv_test_video);
        tv_test_game = (TextView) findViewById(R.id.tv_test_game);
        tv_about_speed_test = (TextView) findViewById(R.id.tv_about_speed_test);
        tv_test_speed_hint = (TextView) findViewById(R.id.tv_test_speed_hint);

        tv_speed = (TextView) findViewById(R.id.tv_speed);

        iv_hand_of_dial = (ImageView) findViewById(R.id.iv_the_hand_of_speed_dial);

        tv_test_site.setOnClickListener(this);
        btn_start_test.setOnClickListener(this);
        tv_test_video.setOnClickListener(this);
        tv_test_game.setOnClickListener(this);
        tv_about_speed_test.setOnClickListener(this);

    }

    @Override
    protected void initViewData() {
        new TestSpeedServ().getTestSpeedIpItems(this);
    }

    @Override
    protected void registMsg() {}

    @Override
    protected void unRegistMsg() {}

    private void startRotatingOrNot (boolean isHandRotating) {
        if (isHandRotating) {
            iv_hand_of_dial.setVisibility(View.VISIBLE);
            iv_hand_of_dial.startAnimation(animation);
        } else {
            iv_hand_of_dial.clearAnimation();
            iv_hand_of_dial.setVisibility(View.GONE);
        }
    }

    private String transSpeed (double speed) {
        System.err.println("第"+timeStamp+"秒=============================="+speed);

        if (speed < 1024) {
            return reserved2decimal(speed, "B/S");
        } else if ((speed / 1024) < 1024) {
            return reserved2decimal(speed / 1024, "KB/S");
        } else if (speed / (1024 * 1024) < 1024) {
            return reserved2decimal(speed / (1024 * 1024), "MB/S");
        }
        return "<big>__ __</big><br/>KB/s";
    }

    //保留两位小数
    private String reserved2decimal (double speed, String units) {
        //对结果进行保存两位小数(四舍五入)
        BigDecimal bigDecimal = new BigDecimal(speed);
        speed = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        return "<big>"+speed+"</big>"+ "<br/>"+units;
    }

    //获取最大的速度(冒泡)
    private void getMaxspeed (double speed) {
        if (max_speed < speed) {
            max_speed = speed;
            System.err.println("最大的速度byte/s"+max_speed);
        }
    }

    //正式开始测速
    private void startTestSpeed() {

        if (!isHandRotating && (list.size() > 0)) {

            isHandRotating = true;
            startRotatingOrNot(isHandRotating);

            btn_start_test.setText("正在测速...");
            tv_test_speed_hint.setText("正在进行宽带测速,整个过程大概需要20秒");

            for (String ipItems : list) {
                new MyThread(ipItems).start();
            }
            timer = new Timer(); 
            myTask = new MyTask();
            timer.schedule(myTask, 0, 1000);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_start_test:{
            startTestSpeed();
            break;
        }
        case R.id.tv_test_site:{
            //跳转到网页测速
            getContext().startActivity(new Intent(getContext(), TestSiteSpeedActivity.class));
            break;
        }
        case R.id.tv_test_video:{
            //跳转到视频测速
            getContext().startActivity(new Intent(getContext(), TestVideoSpeedActivity.class));
            break;
        }
        case R.id.tv_test_game:{
            //跳转到游戏测速
            getContext().startActivity(new Intent(getContext(), TestGameSpeedActivity.class));
            break;
        }
        case R.id.tv_about_speed_test:{
            //跳转到关于测速
            getContext().startActivity(new Intent(getContext(), AboutSpeedTestActivity.class));
            break;
        }

        default:
            break;
        }

    }

    private String getExtractNetIp (String strXml) {
        int i = strXml.indexOf("[")+1;
        int j = strXml.indexOf("]", i);
        return (strXml.substring(i, j));
    }

    private List<String> getExtractTestIp (String strXml) {
        int x = strXml.indexOf("<RegionNodeIp>")+14;
        int y  = strXml.indexOf("</RegionNodeIp>", x);
        strXml = strXml.substring(x, y);
        String[] ipItems = strXml.split(",");

        for (int i = 0; i < ipItems.length; i++) {
            if (!testIpList.contains(ipItems[i])) {
                testIpList.add(ipItems[i]);
            }
        }
        System.out.println(strXml);
        return testIpList;
    }

    public void testSpeed (String ipAddress) {
        int port = 20000;
        double length;
        Socket socket;
        InputStream inputStream = null;
        double startTime = 0;
        double estimatedTime = 0;
        final double MAX_DOWNLOAD_TIME = 15;

        try {
            socket = new Socket(ipAddress, port);
            inputStream = socket.getInputStream();
            byte[] buffer = new byte[1024 * 4];
            PrintStream out = null;
            out = new PrintStream(socket.getOutputStream());
            out.print("start;");
//          startTime = System.nanoTime();

            while ((length = inputStream.read(buffer)) != -1) {
//              estimatedTime = (System.nanoTime() - startTime) / 1000000000;
                //统计下载量
                if (MAX_DOWNLOAD_TIME >= timeStamp ) {
                    allThreadDownloadLength += length;
                }
                //到十五跳出
                else {
                    socket.close();
                    break;
                }

            }
            socket.close();
        } catch (Exception e) {
            System.out.println("出错了");
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    class MyThread extends Thread {
        private String ipAddress;

        @Override
        public void run() {
            testSpeed(ipAddress);
        }

        MyThread (String ipAddress) {
            this.ipAddress = ipAddress;
            System.err.println("传入的Ipitems"+ipAddress);
        }
    }

    private void sendMessage (int what, String speed) {
        Message message = new Message();
        message.what = what;
        Bundle data = new Bundle();
        data.putString("speed", speed+"");
        message.setData(data);
        handler.sendMessage(message);
    }

//  public static String sendGet (String url) {
//      String result ="";
//      BufferedReader in = null;
//      try {
//          URL getUrl = new URL(url);
//          // 打开同url之间的连接
//          URLConnection connection = getUrl.openConnection();
//          //建立实际的连接
//          connection.connect();
//          
//          in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//          String line;
//          while ((line = in.readLine()) != null) {
//              result += line;
//          }
//      } catch (Exception e) {
//          System.err.println("发送GET请求出现异常"+e);
//          e.printStackTrace();
//      } finally {
//          if (in != null) {
//              try {
//                  in.close();
//              } catch (IOException e) {
//                  e.printStackTrace();
//              }
//          } 
//      }
//      return result;
//  }


    @Override
    public boolean onFinish(CmdTask task, String jsResult) {
        System.err.println("测速************************************"+jsResult);
        switch (task.getCmd()) {
        case GET_EXTRACT_IP:{
//          String extractNetIp = getExtractNetIp(jsResult);
//          new TestSpeedServ().getTestSpeedIpItems(extractNetIp, this);
            break;
        }
        case GET_TEST_SPEED_IPITEMS:{
            list = getExtractTestIp(jsResult);
            break;
        }
        default:
            break;
        }
        return false;
    }
}

Android.gitignore

# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.