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

相关文章

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.