安卓day28网络编程 handler 引用 网络文件获取 缓存图片 smartimageview框架 xml文件下载显示 网站验证密码 get post...

一、排坑

static Handler handler;Handler内存泄漏

Handler要解决的根本问题是Android线程并发,如果没有相应的机制约束各线程的协作并发,很容易导致开发上和运行上的混乱。Android处理多线程的方式也不是传统上的加锁机制(性能因素吧),而是MessageQueue,即消息队列,开发者可以直接控制消息队列的显示顺序和方式,这样就不会产生数据的同步混乱的问题了。

1. 内存泄露原因分析

由于这个Handler作为内部类声明在Activity内部,普通的内部类对象隐式地保存了一个指向外部类对象的引用,所以这个Handler对象保存了一个指向Activity对象的引用。而这个Handler对象的生命周期可能比Activity生命周期长,比如当有一个后台线程持有该Handler,别且该线程在执行一个长时间任务。所以当该Handler没有被JVM垃圾回收器回收时,它就阻止了它引用的外部类Activity对象的回收,这里就导致了内存泄露。

2. 如何解决这种内存泄露问题

在该内存泄露的Lint Warning中给出了解决该问题的方法。将Handler类声明为静态内部类,即解除内部类对象与其外部类对象之间的联系。创建一个外部类的WeakReference,并在实例化Handler对象时使用它。代码实现如下:

private static class MyHandler extends Handler {

    private WeakReference<MainActivity> activityWeakReference;

    public MyHandler(MainActivity activity) {
        activityWeakReference = new WeakReference<MainActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivity activity = activityWeakReference.get();
        if (activity != null) {

        }
    }
}
  • handler造成内存泄漏是因为在Activity销毁的时候还有未执行完的任务
  • 静态static可以解决内存泄漏
  • 使用弱引用也可以解决内存泄漏,但是需要等到handler的中任务都执行完,才会释放activity内存,不如直接static释放的快
  • handler造成内存泄漏有 两种方案:一种是业务逻辑上,在activity销毁的时候移除所有未执行的任务。一种是从GC上,通过static的Handler或者弱引用解决。但是单独的使用弱引用性能不是太高。

static MainActivity ma;

static变量所指向内存的引用,如果不把它设置为null ,GC是不会回收这个对象的,
所以为了让GC能够回收static变量 我们在使用完后将static变量设置为null

4种引用

SoftReference、WeakReference和PhantomReference

SoftReference、WeakReference和PhantomReference是java.lang.ref类库中的一组类。当垃圾回收器正在考察的对象只能通过某个Reference对象才“可获得”时,这3个类为垃圾回收器提供了不同级别的间接性提示。

对象是可获得的(reachable),是指此对象可在程序中的某处找到。这意味着你在栈中有一个普通的“引用A”,而它正指向此“对象A”,也可能是“引用B”指向“对象B”,而“对象B”含有“引用C”指向“对象A”,也可能是更多的中间链接。如果一个对象是“可获得的”,垃圾回收器就不能释放它,因为它仍然为你的程序所用。如果一个对象不是“可获得的”,那么你的程序将无法使用到它,所以将其回收是安全的。

如果想继续持有某个对象的引用,想以后还能够访问到该对象,同时也想在内存消耗殆尽的时候垃圾回收器回收它,这时就应该使用Reference对象。

SoftReference、WeakReference和PhantomReference由强到弱排列,表示不同级别的“可获得性”。

SoftReference用以实现内存敏感的高速缓存。

WeakReference是为实现“规范映射”(canonicalizing mappings)而设计的,它不妨碍垃圾回收器回收映射的“键”(或“值”)。“规范映射”中对象的实例可以在程序的多处被同时使用,以节省存储空间。

PhantomReference用以调度回收前的清理工作,它比Java终止机制更加灵活。

https://blog.csdn.net/bell10027/article/details/50349713

variable xxx is accessed from within inner class; needs to be declared final

在内部类当中不能引用本地变量,需要被声明为常量

Server Tomcat v7.0 Server at localhost failed to start

可以选择删除web.xml中的映射,也可以选择将servlet自动生成的注解注释掉,这样就不会有冲突了,二者选其一留下即可。

get方式中文乱码

在Get方式请求中request.setCharacterEncoding("UTF-8")不再起作用

        String name = request.getParameter("name");
        name = new String(name.getBytes("ISO-8859-1"),"UTF-8");

 

二、网络图片查看器

主线程不能被阻塞

  • 在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差
  • 主线程阻塞时间过长,系统会抛出ANR异常
  • ANR:Application Not Response;应用无响应
  • 任何耗时操作都不可以写在主线程
  • 因为网络交互属于耗时操作,如果网速很慢,代码会阻塞,所以网络交互的代码不能运行在主线程

只有主线程能刷新ui

  • 刷新ui的代码只能运行在主线程,运行在子线程是没有任何效果的
  • 如果需要在子线程中刷新ui,使用消息队列机制

消息队列

  • Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息
  • handleMessage方法运行在主线程
  • 主线程创建时,消息队列和轮询器对象就会被创建,但是消息处理器对象,需要使用时,自行创建

public class MainActivity extends Activity {

    static ImageView iv;
    static MainActivity ma;

    static Handler handler = new Handler(){
        //此方法在主线程中调用,可以用来刷新ui
        public void handleMessage(Message msg) {
            //处理消息时,需要知道到底是成功的消息,还是失败的消息
            switch (msg.what) {
            case 1:
                //把位图对象显示至imageview
                iv.setImageBitmap((Bitmap)msg.obj);
                break;

            case 0:
                Toast.makeText(ma, "请求失败", Toast.LENGTH_SHORT).show();
                break;
            }
            ma=null;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
        ma = this;
    }
    public void click(View v){
        getpic("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551414968179&di=2896146dee79c07b8a5ea400d35cd9ff&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F5243fbf2b211931330751d8b6b380cd791238dd3.jpg");
    }
    public void click2(View v){
        getpic("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551425560734&di=81f2206ede868b4ceb7d33a47f6f68f2&imgtype=0&src=http%3A%2F%2Fd.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2Fe7cd7b899e510fb3a4c06fa8d733c895d1430c37.jpg");
    }
    public void getpic(String path){
        final String path1=path;
        Thread t = new Thread(){
            @Override
            public void run() {
                //下载图片
                //1.确定网址
                //String path = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551414968179&di=2896146dee79c07b8a5ea400d35cd9ff&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F5243fbf2b211931330751d8b6b380cd791238dd3.jpg";
                try {
                    //2.把网址封装成一个url对象
                    URL url = new URL(path1);
                    //3.获取客户端和服务器的连接对象,此时还没有建立连接
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    //4.对连接对象进行初始化
                    //设置请求方法,注意大写
                    conn.setRequestMethod("GET");
                    //设置连接超时
                    conn.setConnectTimeout(5000);
                    //设置读取超时
                    conn.setReadTimeout(5000);
                    //5.发送请求,与服务器建立连接
                    conn.connect();
                    //如果响应码为200,说明请求成功
                    if(conn.getResponseCode() == 200){
                        //获取服务器响应头中的流,流里的数据就是客户端请求的数据
                        InputStream is = conn.getInputStream();
                        //读取出流里的数据,并构造成位图对象
                        Bitmap bm = BitmapFactory.decodeStream(is);
                        
//                        ImageView iv = (ImageView) findViewById(R.id.iv);
//                        //把位图对象显示至imageview
//                        iv.setImageBitmap(bm);
                        
                        Message msg = new Message();
                        //消息对象可以携带数据
                        msg.obj = bm;
                        msg.what = 1;
                        //把消息发送至主线程的消息队列
                        handler.sendMessage(msg);
                    }
                    else{
//                        Toast.makeText(MainActivity.this, "请求失败", 0).show();
                        
                        Message msg = handler.obtainMessage();
                        msg.what = 0;
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        t.start();
    }
}

加入缓存图片的功能

    public void getpic2(String path){
        //下载图片
        //1.确定网址
        final String path1=path;
        final File file = new File(getCacheDir(), getFileName(path));
        //判断,缓存中是否存在该文件
        if(file.exists()){
            //如果缓存存在,从缓存读取图片
            Log.e(TAG, "从缓存读取的: ");
            Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
            iv.setImageBitmap(bm);
        }
        else{
            //如果缓存不存在,从网络下载
            Log.e(TAG, "从网上下载的: ");
            Thread t = new Thread(){
                @Override
                public void run() {

                    try {
                        //2.把网址封装成一个url对象
                        URL url = new URL(path1);
                        //3.获取客户端和服务器的连接对象,此时还没有建立连接
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        //4.对连接对象进行初始化
                        //设置请求方法,注意大写
                        conn.setRequestMethod("GET");
                        //设置连接超时
                        conn.setConnectTimeout(5000);
                        //设置读取超时
                        conn.setReadTimeout(5000);
                        //5.发送请求,与服务器建立连接
                        conn.connect();
                        //如果响应码为200,说明请求成功
                        if(conn.getResponseCode() == 200){
                            //获取服务器响应头中的流,流里的数据就是客户端请求的数据
                            InputStream is = conn.getInputStream();

                            //读取服务器返回的流里的数据,把数据写到本地文件,缓存起来

                            FileOutputStream fos = new FileOutputStream(file);
                            byte[] b = new byte[1024];
                            int len = 0;
                            while((len = is.read(b)) != -1){
                                fos.write(b, 0, len);
                            }
                            fos.close();

                            //读取出流里的数据,并构造成位图对象
                            //流里已经没有数据了
//                            Bitmap bm = BitmapFactory.decodeStream(is);
                            Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());


                            Message msg = new Message();
                            //消息对象可以携带数据
                            msg.obj = bm;
                            msg.what = 1;
                            //把消息发送至主线程的消息队列
                            handler.sendMessage(msg);

                        }
                        else{
//                            Toast.makeText(MainActivity.this, "请求失败", 0).show();

                            Message msg = handler.obtainMessage();
                            msg.what = 0;
                            handler.sendMessage(msg);
                        }
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            };
            t.start();
        }
    }
    public String getFileName(String path){
        int index = path.lastIndexOf("/");
        return path.substring(index + 1);
    }

 

三、SmartImageView

源码:https://github.com/loopj/android-smart-image-view

开源项目SmartImageView的出现主要是为了加速从网络上加载图片,它继承自ImageView类,支持根据URL地址加载图片,支持异步加载图片,支持图片缓存等。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下载图片" 
        android:onClick="click"
        />

    <com.loopj.android.image.SmartImageView 
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</RelativeLayout>
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void click(View v){
        //下载图片
        //1.确定网址
        String path = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551414968179&di=2896146dee79c07b8a5ea400d35cd9ff&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F5243fbf2b211931330751d8b6b380cd791238dd3.jpg";
        //2.找到智能图片查看器对象
        SmartImageView siv = (SmartImageView) findViewById(R.id.iv);
        //3.下载并显示图片
        siv.setImageUrl(path);
    }

}

四、Html源文件查看器

public class MainActivity extends Activity {

    Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setText((String)msg.obj);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void click(View v){
        Thread t = new Thread(){
            @Override
            public void run() {
                String path = "https://www.cnblogs.com/index42/p/10438061.html";
                try {
                    URL url = new URL(path);
                    //获取连接对象,此时还未建立连接
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    //先建立连接,然后获取响应码
                    if(conn.getResponseCode() == 200){
                        //拿到服务器返回的输入流,流里的数据就是html的源文件
                        InputStream is = conn.getInputStream();
                        //从流里把文本数据取出来
                        String text = Utils.getTextFromStream(is);
                        
                        //发送消息,让主线程刷新ui,显示源文件
                        Message msg = handler.obtainMessage();
                        msg.obj = text;
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        t.start();
    }
}
public class Utils {

    public static String getTextFromStream(InputStream is){
        
        byte[] b = new byte[1024];
        int len = 0;
        //创建字节数组输出流,读取输入流的文本数据时,同步把数据写入数组输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            while((len = is.read(b)) != -1){
                bos.write(b, 0, len);
            }
            //把字节数组输出流里的数据转换成字节数组
            String text = new String(bos.toByteArray());
            return text;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

五、小志新闻客户端

上传文件提供下载链接

public class MainActivity extends Activity {

    List<News> newsList;
    Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            ListView lv = (ListView) findViewById(R.id.lv);
            lv.setAdapter(new MyAdapter());
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        getNewsInfo();
//        ListView lv = (ListView) findViewById(R.id.lv);
//        //要保证在设置适配器时,新闻xml文件已经解析完毕了
//        lv.setAdapter(new MyAdapter());
    }

    class MyAdapter extends BaseAdapter{

        //得到模型层中元素的数量,用来确定listview需要有多少个条目
        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return newsList.size();
        }
        @Override
        //返回一个View对象,作为listview的条目显示至界面
        public View getView(int position, View convertView, ViewGroup parent) {

            News news = newsList.get(position);
            View v = null;
            ViewHolder mHolder;
            if(convertView == null){
                v = View.inflate(MainActivity.this, R.layout.item_listview, null);
                mHolder = new ViewHolder();
                //把布局文件中所有组件的对象封装至ViewHolder对象中
                mHolder.tv_title = (TextView) v.findViewById(R.id.tv_title);
                mHolder.tv_detail = (TextView) v.findViewById(R.id.tv_detail);
                mHolder.tv_comment = (TextView) v.findViewById(R.id.tv_comment);
                mHolder.siv = (SmartImageView) v.findViewById(R.id.iv);
                //把ViewHolder对象封装至View对象中
                v.setTag(mHolder);
            }
            else{
                v = convertView;
                mHolder = (ViewHolder) v.getTag();
            }
            //给三个文本框设置内容
            mHolder.tv_title.setText(news.getTitle());
            
            mHolder.tv_detail.setText(news.getDetail());
            
            mHolder.tv_comment.setText(news.getComment() + "条评论");
            
            //给新闻图片imageview设置内容
            mHolder.siv.setImageUrl(news.getImageUrl());
            return v;
        }
        
        class ViewHolder{
            //条目的布局文件中有什么组件,这里就定义什么属性
            TextView tv_title;
            TextView tv_detail;
            TextView tv_comment;
            SmartImageView siv;
        }
        
        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }
    }
    private void getNewsInfo() {
        Thread t = new Thread(){
            @Override
            public void run() {
                String path = "https://files.cnblogs.com/files/index42/news.xml";
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    //发送http GET请求,获取相应码
                    if(conn.getResponseCode() == 200){
                        InputStream is = conn.getInputStream();
                        //使用pull解析器,解析这个流
                        parseNewsXml(is);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        t.start();
    }
    
    private void parseNewsXml(InputStream is) {
        XmlPullParser xp = Xml.newPullParser();
        try {
            xp.setInput(is, "utf-8");
            //对节点的事件类型进行判断,就可以知道当前节点是什么节点
            int type = xp.getEventType();
            News news = null;
            while(type != XmlPullParser.END_DOCUMENT){
                switch (type) {
                case XmlPullParser.START_TAG:
                    if("newslist".equals(xp.getName())){
                        newsList = new ArrayList<News>();
                    }
                    else if("news".equals(xp.getName())){
                        news = new News();
                    }
                    else if("title".equals(xp.getName())){
                        String title = xp.nextText();
                        news.setTitle(title);
                    }
                    else if("detail".equals(xp.getName())){
                        String detail = xp.nextText();
                        news.setDetail(detail);
                    }
                    else if("comment".equals(xp.getName())){
                        String comment = xp.nextText();
                        news.setComment(comment);
                    }
                    else if("image".equals(xp.getName())){
                        String image = xp.nextText();
                        news.setImageUrl(image);
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if("news".equals(xp.getName())){
                        newsList.add(news);
                    }
                    break;

                }
                //解析完当前节点后,把指针移动至下一个节点,并返回它的事件类型
                type = xp.next();
            }
            
            //发消息,让主线程设置listview的适配器,如果消息不需要携带数据,可以发送空消息
            handler.sendEmptyMessage(1);
            
//            for (News n : newsList) {
//                System.out.println(n.toString());
//            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
public class News {

    private String title;
    private String detail;
    private String comment;
    private String imageUrl;
    
    @Override
    public String toString() {
        return "News [title=" + title + ", detail=" + detail + ", comment="
                + comment + ", imageUrl=" + imageUrl + "]";
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
    
    <com.loopj.android.image.SmartImageView 
        android:id="@+id/iv"
        android:layout_width="90dp"
        android:layout_height="70dp"
        android:src="@drawable/ic_launcher_background"
        android:layout_centerVertical="true"
        />
    <TextView 
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是大标题志哥教你上塑料adasfsadfdsfdsgsd"
        android:layout_toRightOf="@id/iv"
        android:textSize="22sp"
        android:singleLine="true"
        />
     <TextView 
         android:id="@+id/tv_detail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是正文志哥教你带崩三路adasfsadasdasdasdasidhsakjhdkjashdkjahskjdhsakjdfdsfdsgsd"
        android:layout_toRightOf="@id/iv"
        android:layout_below="@id/tv_title"
        android:textSize="15sp"
        android:textColor="@android:color/darker_gray"
        android:lines="2"
        />
      <TextView 
          android:id="@+id/tv_comment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="65031条评论"
        android:textColor="#ff0000"
        android:layout_alignParentRight="true"
        android:layout_below="@id/tv_detail"
        />
</RelativeLayout>

六、提交数据

本地网站服务器准备工作

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doPost(request,response);
        //response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //request.setCharacterEncoding("UTF-8");
         response.setContentType("text/html;charset=UTF-8");

            String username = request.getParameter("username");
            String username1 =new String(username.getBytes("ISO-8859-1"),"UTF-8");
            String password = request.getParameter("password");

            PrintWriter out = response.getWriter();
            out.println("<p>"+username1+"</p>");
            out.println("<p>"+password+"</p>");
            if(username.equals("admin")&&password.equals("123456")){
                out.println("<p>登录成功!"+"</p>");
            }
            else{
                out.println("<p>用户名或密码错误!"+"</p>");
            }
            out.flush();
            out.close();
    }

}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Login</title>
</head>
<body>

<form action="/d0301/LoginServlet" method="post">
  <p>用户名:<input name="username" type="text"><p>
  <p>&nbsp;&nbsp;&nbsp;码:<input name="password" type="password"></p>
  <p><input type="submit" value="提交"/>&nbsp;&nbsp;<input type="reset" value="重置"></p>
</form>

</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name></display-name>
  <servlet>
      <servlet-name>LoginServlet</servlet-name>
      <servlet-class>hmk.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>LoginServlet</servlet-name>
      <url-pattern>/LoginServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

可用电脑上的安卓模拟器调试

GET方式提交数据

浏览器在发送请求携带数据时会对数据进行URL编码,我们写代码时也需要为中文进行URL编码

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            Toast.makeText(MainActivity.this, (String)msg.obj, Toast.LENGTH_SHORT).show();
        }
    };
    
    public void click(View v){
        EditText et_name = (EditText) findViewById(R.id.et_name);
        EditText et_pass = (EditText) findViewById(R.id.et_pass);
        
        final String name = et_name.getText().toString();
        final String pass = et_pass.getText().toString();
        
        Thread t = new Thread(){
            @Override
            public void run() {
                //提交的数据需要经过url编码,英文和数字编码后不变
                @SuppressWarnings("deprecation")
                String path = "http://10.32.189.73:8080/d0301/LoginServlet?username=" + URLEncoder.encode(name) + "&password=" + pass;
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    
                    if(conn.getResponseCode() == 200){
                        InputStream is =conn.getInputStream();
                        String text = Utils.getTextFromStream(is);
                        
                        Message msg = handler.obtainMessage();
                        msg.obj = text;
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        t.start();
    }
}

POST方式提交数据

  • post提交数据是用流写给服务器的
  • 协议头中多了两个属性

    • Content-Type: application/x-www-form-urlencoded,描述提交的数据的mimetype
    • Content-Length: 32,描述提交的数据的长度

    public void click2(View v){
        EditText et_name = (EditText) findViewById(R.id.et_name);
        EditText et_pass = (EditText) findViewById(R.id.et_pass);

        final String name = et_name.getText().toString();
        final String pass = et_pass.getText().toString();

        Thread t = new Thread(){
            @Override
            public void run() {
                //提交的数据需要经过url编码,英文和数字编码后不变
                @SuppressWarnings("deprecation")
                String path = "http://10.32.189.73:8080/d0301/LoginServlet";

                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);

                    //拼接出要提交的数据的字符串
                    String data = "username=" + URLEncoder.encode(name) + "&password=" + pass;
                    //添加post请求的两行属性
                    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    conn.setRequestProperty("Content-Length", data.length() + "");

                    //设置打开输出流
                    conn.setDoOutput(true);
                    //拿到输出流
                    OutputStream os = conn.getOutputStream();
                    //使用输出流往服务器提交数据
                    os.write(data.getBytes());
                    if(conn.getResponseCode() == 200){
                        InputStream is = conn.getInputStream();
                        String text = Utils.getTextFromStream(is);

                        Message msg = handler.obtainMessage();
                        msg.obj = text;
                        handler.sendMessage(msg);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        t.start();
    }
}

 

转载于:https://www.cnblogs.com/index42/p/10451822.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值