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

相关文章

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

使用 Python 和 LabelMe 实现图片验证码的自动标注功能

《使用Python和LabelMe实现图片验证码的自动标注功能》文章介绍了如何使用Python和LabelMe自动标注图片验证码,主要步骤包括图像预处理、OCR识别和生成标注文件,通过结合Pa... 目录使用 python 和 LabelMe 实现图片验证码的自动标注环境准备必备工具安装依赖实现自动标注核心

Java操作xls替换文本或图片的功能实现

《Java操作xls替换文本或图片的功能实现》这篇文章主要给大家介绍了关于Java操作xls替换文本或图片功能实现的相关资料,文中通过示例代码讲解了文件上传、文件处理和Excel文件生成,需要的朋友可... 目录准备xls模板文件:template.xls准备需要替换的图片和数据功能实现包声明与导入类声明与

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

基于C#实现将图片转换为PDF文档

《基于C#实现将图片转换为PDF文档》将图片(JPG、PNG)转换为PDF文件可以帮助我们更好地保存和分享图片,所以本文将介绍如何使用C#将JPG/PNG图片转换为PDF文档,需要的可以参考下... 目录介绍C# 将单张图片转换为PDF文档C# 将多张图片转换到一个PDF文档介绍将图片(JPG、PNG)转

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影