Android_04_网络图片查看器

2024-05-19 09:58

本文主要是介绍Android_04_网络图片查看器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1>不带缓存的图片查看器

MainActivity.java

package com.ithiema.imageviewer;import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;public class MainActivity extends Activity {Handler handler = new Handler(){//此方法在主线程中调用,可以用来刷新uipublic void handleMessage(android.os.Message msg) {//处理刷新UI的操作需要在主线程中,通过子线程handler.sendMessage(msg);//即可触发主线程去调用主线程的handleMessage()方法;//所以关于子线程中刷新UI的操作都到handleMessage()方法中来做;//处理消息时,需要知道到底是成功的消息,还是失败的消息switch (msg.what) {case 1://把位图对象显示至imageviewImageView iv = (ImageView) findViewById(R.id.iv);iv.setImageBitmap((Bitmap)msg.obj);break;case 0:Toast.makeText(MainActivity.this, "请求失败", 0).show();break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){Thread t = new Thread(){@Overridepublic void run() {//下载图片//1.确定网址String path = "http://192.168.1.103:8080/1.jpg";try {//2.把网址封装成一个url对象URL url = new URL(path);//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);//除了new Message()一个Message之外,也可以通过Message.obtain()//获得Message对象,还可以通过handler.obtainMessage(),可自行查看源码;Message msg = new Message();//消息对象可以携带数据msg.obj = bm;//msg.what是为了区分多个message,以便在主线程的handleMessage()方法中去区分//哪个消息是哪个发送的msg.what = 1;//把消息发送至主线程的消息队列handler.sendMessage(msg);}else{//Toast.makeText(MainActivity.this, "请求失败", 0).show();Message msg = handler.obtainMessage();//msg.what是为了区分多个message,以便在主线程的handleMessage()方法中去区分//哪个消息是哪个发送的msg.what = 0;//把消息发送至主线程的消息队列,让主线程去处理;handler.sendMessage(msg);}} catch (Exception e) {e.printStackTrace();}}};t.start();}}

activity_main.xml

<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"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><Button android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下载图片"android:onClick="click"/><ImageViewandroid:id="@+id/iv"android:layout_width="wrap_content"android:layout_height="wrap_content"/></RelativeLayout>
注:对于网络下载这块,需要在清单文件中添加一条权限:

<uses-permission android:name="android.permission.INTERNET"/>




注:

I. 主线程不能被阻塞
在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差
主线程阻塞时间过长,系统会抛出ANR异常
ANR:Application Not Response;应用无响应
任何耗时操作都不可以写在主线程
因为网络交互属于耗时操作,如果网速很慢,代码会阻塞,所以网络交互的代码不能运行在主线程
II. 只有主线程能刷新ui
刷新ui的代码只能运行在主线程,运行在子线程是没有任何效果的
如果需要在子线程中刷新ui,使用消息队列机制
III. 消息队列
Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息
handleMessage方法运行在主线程
主线程创建时,消息队列和轮询器对象就会被创建,但是消息处理器对象,需要使用时,自行创建

        //消息队列
        Handler handler = new Handler(){
            //主线程中有一个消息轮询器looper,不断检测消息队列中是否有新消息,如果发现有新消息,自动调用此方法,注意此方法是在主线程中运行的
            public void handleMessage(android.os.Message msg) {
        
            }
        };
在子线程中往消息队列里发消息
        //创建消息对象
        Message msg = new Message();
        //消息的obj属性可以赋值任何对象,通过这个属性可以携带数据,若有多个数据,可以定义一个数组或集合类对象;
        msg.obj = bm;
        //what属性相当于一个标签,用于区分出不同的消息,从而运行不能的代码
        msg.what = 1;
        //发送消息
        handler.sendMessage(msg);


2>进一步优化

也就是把Handler对象变成一个static对象,那么所有对象都只共用这一个静态变量,

那么这个应用的其他的类也可以直接调用,方便快捷;activity_main.xml文件无需修改;

MainActivity.java

package com.ithiema.imageviewer;import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;public class MainActivity extends Activity {static ImageView iv;static MainActivity ma;static Handler handler = new Handler(){//此方法在主线程中调用,可以用来刷新uipublic void handleMessage(android.os.Message msg) {//处理消息时,需要知道到底是成功的消息,还是失败的消息switch (msg.what) {case 1://把位图对象显示至imageviewiv.setImageBitmap((Bitmap)msg.obj);break;case 0:Toast.makeText(ma, "请求失败", 0).show();break;}}};@Overrideprotected 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){Thread t = new Thread(){@Overridepublic void run() {//下载图片//1.确定网址String path = "http://192.168.13.13:8080/dd.jpg";try {//2.把网址封装成一个url对象URL url = new URL(path);//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 blocke.printStackTrace();}}};t.start();}}




3>待缓存的图片查看器

MainActivity.java

package com.ithiema.imageviewer;import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;import com.ithiema.cacheimageviewer.R;import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;public class MainActivity extends Activity {ImageView iv = (ImageView) findViewById(R.id.iv);Handler handler = new Handler(){//此方法在主线程中调用,可以用来刷新uipublic void handleMessage(android.os.Message msg) {//处理消息时,需要知道到底是成功的消息,还是失败的消息switch (msg.what) {case 1://把位图对象显示至imageviewiv.setImageBitmap((Bitmap)msg.obj);break;case 0:Toast.makeText(MainActivity.this, "请求失败", 0).show();break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){//下载图片//1.确定网址final String path = "http://192.168.1.103:8080/1.jpg";final File file = new File(getCacheDir(), getFileName(path));//判断,缓存中是否存在该文件if(file.exists()){//如果缓存存在,从缓存读取图片System.out.println("从缓存读取的");Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());iv.setImageBitmap(bm);}else{//如果缓存不存在,从网络下载System.out.println("从网上下载的");Thread t = new Thread(){@Overridepublic void run() {try {//2.把网址封装成一个url对象URL url = new URL(path);//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();//读取出流里的数据,并构造成位图对象//流里已经没有数据了,所以BitmapFactory.decodeStream(is)此时就失效了,//因为被is.read已经读取了;所以用BitmapFactory.decodeFile()方法生成Bitmap对象;
//							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{							Message msg = handler.obtainMessage();msg.what = 0;handler.sendMessage(msg);}} catch (Exception e) {e.printStackTrace();}}};t.start();}}//这是自行定义的一个方法,用于获取path变量所存放的文件名,这种封装的思想要学会!public String getFileName(String path){int index = path.lastIndexOf("/");return path.substring(index + 1);}}

activity_main.xml

<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"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><Button android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下载图片"android:onClick="click"/><ImageViewandroid:id="@+id/iv"android:layout_width="wrap_content"android:layout_height="wrap_content"/></RelativeLayout>


注:关于网络图片查看器,上述部分只是其核心部分,很多细节都没有考虑到位,你也可参考网上的做法;

如你在做每个项目时,都可以去http://github.com或http://code.geogle.com去查看别人所写的类似的开源项目,

多学会学习学习别人思想的精髓







这篇关于Android_04_网络图片查看器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/995802

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel