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

相关文章

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

使用Python实现base64字符串与图片互转的详细步骤

《使用Python实现base64字符串与图片互转的详细步骤》要将一个Base64编码的字符串转换为图片文件并保存下来,可以使用Python的base64模块来实现,这一过程包括解码Base64字符串... 目录1. 图片编码为 Base64 字符串2. Base64 字符串解码为图片文件3. 示例使用注意

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

Linux网络配置之网桥和虚拟网络的配置指南

《Linux网络配置之网桥和虚拟网络的配置指南》这篇文章主要为大家详细介绍了Linux中配置网桥和虚拟网络的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、网桥的配置在linux系统中配置一个新的网桥主要涉及以下几个步骤:1.为yum仓库做准备,安装组件epel-re

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细