日期: 2021 年 6 月 25 日

使用Android-Universal-Image-Loader加载网络图片

使用Android-Universal-Image-Loader加载网络图片
Android-Universal-Image-Loader是一个开源的Android图片加载辅助组件,其主要目的是图片加载,缓存,显示。提供了一系列配置选项和图片加载,缓存的控制。

Android-Universal-Image-Loader的开源代码里本身是有示例代码的,在这里我们同样写一段代码,在界面上有一个GridView.然后从网络加载图片到GridView。

关于页面上下滑动,图片加载的问题,可以实现一个AbsListView.OnScrollListener,在滑动的时候,触发notifyDataSetChanged来更新整个GridView所有的Item的View。但是从高效的角度,应该只刷新对应的View即可,因为新的Item滑出的时候,本来就是通过adapter的getView()返回应该刷新的那个Item的View,而对于其他已经存在的Item,是不需要在重新加载的。

Android-Universal-Image-Loader很好地解决图片异步加载的问题。在getView()中再去通过ImageLoader.displayImage()来从网络中获取图片也可以。它会把图片获取任务交给线程池去操作。在数据返回后,再将图像赋给ImageView。

代码用到了以下开源库
Android-Universal-Image-Loader:请求,缓存,加载网络图片
jsoup:HTML解析库

效果图:

%title插图%num
源码:

manifest 记得加权限
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

主界面LayOut
<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” >

<GridView
android:id=”@+id/gridView1″
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:layout_centerHorizontal=”true”
android:layout_marginBottom=”40dp”
android:horizontalSpacing=”4dp”
android:verticalSpacing=”4dp”
android:stretchMode=”columnWidth”
android:numColumns=”3″ >
</GridView>

</RelativeLayout>

Item的layout
<?xml version=”1.0″ encoding=”utf-8″?>
<com.example.gridpic.SquareLayout xmlns:android=”http://schemas.android.com/apk/res/android”

android:layout_gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
>
<!– 把图片不按比例扩大/缩小到View的大小显示 –>
<ImageView
android:id=”@+id/imageView1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:scaleType=”fitXY”
/>

</com.example.gridpic.SquareLayout>

自定义的一个Layout
用来wrap每一个Item。为了锁定图片为正方形。

package com.example.gridpic;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
//参考http://blog.chengyunfeng.com/?p=465
//帮助锁定GridView的Item的长宽。
public class SquareLayout extends RelativeLayout {
public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public SquareLayout(Context context) {
super(context);
}

@SuppressWarnings(“unused”)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));

// Children are just made to fill our space.
int childWidthSize = getMeasuredWidth();
int childHeightSize = getMeasuredHeight();
//高度和宽度一样
heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
};
}

##自定义的BaseAdapter
通过ImageLoader加载每幅图片,如果之前已经有本地缓存了,则从本地直接读取
“`java
package com.example.gridpic;

import java.util.List;

import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.BaseAdapter;
import android.widget.ImageView;

public class MyAdapter extends BaseAdapter {
List<String> imageList;
protected ImageLoader imageLoader = ImageLoader.getInstance();
protected DisplayImageOptions options;
private LayoutInflater mInflater;
public MyAdapter(Context context,List<String> imageList) {
super();
this.imageList = imageList;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher)
.showImageForEmptyUri(R.drawable.ic_launcher)
.showImageOnFail(R.drawable.ic_launcher).cacheInMemory(true)
.cacheOnDisk(true).bitmapConfig(Bitmap.Config.RGB_565).build();

this.mInflater = LayoutInflater.from(context);
//初始化ImageLoader
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(
context);
config.threadPriority(Thread.NORM_PRIORITY – 2);
config.denyCacheImageMultipleSizesInMemory();
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.tasksProcessingOrder(QueueProcessingType.LIFO);
config.writeDebugLogs(); // Remove for release app
ImageLoader.getInstance().init(config.build());
}

@Override
public int getCount() {
return imageList.size();
}

@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
if (view == null) {
view = mInflater.inflate(R.layout.picitem, null);
holder = new ViewHolder();
holder.image=(ImageView) view.findViewById(R.id.imageView1);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
imageLoader.displayImage(imageList.get(position),
holder.image, options);
Log.e(“whatever”, “Get View:”+position+”. url=”+imageList.get(position));
return view;
}

final class ViewHolder{

public ImageView image;

}

}

<div class=”se-preview-section-delimiter”></div>

主界面Activity
启动后首先从网站获取一个图片URL地址的列表,并保存在List中,然后通过Handler发送给主线程,设定gridView的Adapter。

package com.example.gridpic;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.Log;

import android.widget.GridView;

public class MainActivity extends Activity {
List<String> imageList;
GridView gridView;
volatile Boolean urlReady = false;

Handler myHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView) findViewById(R.id.gridView1);
new Thread(getImageRunnabe).start();// 准备图片URL

myHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0xff:
Log.e(“whatever”, “URL ready”);
MyAdapter mAdapter = new MyAdapter(getApplicationContext(),imageList);
gridView.setAdapter(mAdapter);
break;
default:
break;
}
super.handleMessage(msg);
}
};

}

Runnable getImageRunnabe = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
imageList = getImageURL();
MainActivity.this.myHandler.sendEmptyMessage(0xff);
}
};

// 事先得到一大批图像的URL地址保存在List中,作为网络图片加载的数据源,如果本来手里就有图片的URL链接地址,可以省略此步骤
public ArrayList<String> getImageURL() {

// 4.0之后访问网络不能放在主线程中做
ArrayList<String> imageList = new ArrayList<String>();
String url = “http://www.juzimi.com/meitumeiju?page=”;
for (int i = 1; i < 10; i++) {
String mUrl = url + String.valueOf(i);
Log.e(“whatever”, mUrl);
try {
Document doc = Jsoup.connect(mUrl).get();
Elements es1 = doc.getElementsByClass(“chromeimg”);
for (Element e : es1) {
imageList.add(e.attr(“src”));
}
} catch (IOException e) {
e.printStackTrace();
}
}
urlReady = true;
return imageList;

}

}

<div class=”se-preview-section-delimiter”></div>

*终效果就是:
向下滑动GridView. 新的Item会调用getView来获取View。这时会把请求提交给ImageLoader。ImageLoader如果在本地找不到对应图片。就回去网络上下载。
于是可以看到效果中,图片加载会需要一定时间的效果。

启动应用->向下滑动 过程的log如下:

03-27 18:19:47.673: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=1
03-27 18:19:48.413: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=2
03-27 18:19:49.203: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=3
03-27 18:19:49.743: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=4
03-27 18:19:50.223: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=5
03-27 18:19:51.713: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=6
03-27 18:19:52.333: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=7
03-27 18:19:53.813: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=8
03-27 18:19:54.573: E/whatever(1802): http://www.juzimi.com/meitumeiju?page=9
03-27 18:19:55.643: E/whatever(1802): URL ready
03-27 18:19:55.703: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:55.703: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:55.703: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:55.713: E/whatever(1802): Get View:1. url=http://file.juzimi.com/weibopic/jazdmo2.jpg
03-27 18:19:55.713: E/whatever(1802): Get View:2. url=http://file.juzimi.com/weibopic/juzrmd4.jpg
03-27 18:19:55.713: E/whatever(1802): Get View:3. url=http://file.juzimi.com/weibopic/jozpmp6.jpg
03-27 18:19:55.723: E/whatever(1802): Get View:4. url=http://file.juzimi.com/weibopic/jlzamd1.jpg
03-27 18:19:55.723: E/whatever(1802): Get View:5. url=http://file.juzimi.com/weibopic/jezxmx2.jpg
03-27 18:19:55.723: E/whatever(1802): Get View:6. url=http://file.juzimi.com/weibopic/jozump.jpg
03-27 18:19:55.723: E/whatever(1802): Get View:7. url=http://file.juzimi.com/weibopic/jpzxml3.jpg
03-27 18:19:55.733: E/whatever(1802): Get View:8. url=http://file.juzimi.com/weibopic/jdzumu1.jpg
03-27 18:19:55.733: E/whatever(1802): Get View:9. url=http://file.juzimi.com/weibopic/jazxme.jpg
03-27 18:19:55.733: E/whatever(1802): Get View:10. url=http://file.juzimi.com/weibopic/jpzamr4.jpg
03-27 18:19:55.733: E/whatever(1802): Get View:11. url=http://file.juzimi.com/weibopic/jpzrmd1.jpg
03-27 18:19:55.743: E/whatever(1802): Get View:12. url=http://file.juzimi.com/weibopic/jxzima1.jpg
03-27 18:19:55.743: E/whatever(1802): Get View:13. url=http://file.juzimi.com/weibopic/jrzumx5.jpg
03-27 18:19:55.743: E/whatever(1802): Get View:14. url=http://file.juzimi.com/weibopic/jlzema6.jpg
03-27 18:19:58.243: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:58.253: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:58.543: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:58.543: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:59.413: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:19:59.413: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.003: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.003: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.313: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.313: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.443: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.453: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.983: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:00.983: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.043: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.043: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.183: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.183: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.613: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.613: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.643: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:01.643: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:02.533: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:02.533: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.113: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.113: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.363: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.363: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.793: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:03.793: E/whatever(1802): Get View:0. url=http://file.juzimi.com/weibopic/jozrmu4.jpg
03-27 18:20:09.113: E/whatever(1802): Get View:15. url=http://file.juzimi.com/weibopic/juzemx2.jpg
03-27 18:20:09.113: E/whatever(1802): Get View:16. url=http://file.juzimi.com/weibopic/jpzemo2.jpg
03-27 18:20:09.123: E/whatever(1802): Get View:17. url=http://file.juzimi.com/weibopic/jezrmd5.jpg
03-27 18:20:09.203: E/whatever(1802): Get View:18. url=http://file.juzimi.com/weibopic/jeziml4.jpg
03-27 18:20:09.203: E/whatever(1802): Get View:19. url=http://file.juzimi.com/weibopic/jdzimu4.jpg
03-27 18:20:09.203: E/whatever(1802): Get View:20. url=http://file.juzimi.com/weibopic/jezuml.jpg
03-27 18:20:09.313: E/whatever(1802): Get View:21. url=http://file.juzimi.com/weibopic/jlzrme1.jpg
03-27 18:20:09.313: E/whatever(1802): Get View:22. url=http://file.juzimi.com/weibopic/jozxml.jpg
03-27 18:20:09.313: E/whatever(1802): Get View:23. url=http://file.juzimi.com/weibopic/jozamr.jpg

下一篇文章,会针对这种加载图片延迟的问题进行优化。
————————————————

Universal-Image-Loader 使用详解

UIL出来也很久了,网上的使用方法大多不全,或者是基于老的版本而来的,有必要做些更新了。

因此,下文内容,将基于:v1.9.5版本描述。

以下内容翻译自
Android-Universal-Image-Loader wiki

关于UIL的介绍,不再赘述。

快速设置
添加依赖
添加依赖:

下载jar包并导入你的工程

JAR

使用Maven依赖

<dependency>
<groupId>com.nostra13.universalimageloader</groupId>
<artifactId>universal-image-loader</artifactId>
<version>1.9.5</version>
</dependency>

Gradle依赖

compile ‘com.nostra13.universalimageloader:universal-image-loader:1.9.5’

在Manifest中添加权限:
<manifest>
<!– 添加网络权限,如果需要从网络上下载图片 –>
<uses-permission android:name=”android.permission.INTERNET” />
<!– 添加写外部存储权限,如果需要往sd卡上写图片的话 –>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

</manifest>

在Application或者activity中进行配置,来确保在Application初始化的时候,整个App中有一个ImageLoader存在。
注意:这儿感觉大有文章,在稍后章节详细描述。

// 创建全局的配置来初始化ImageLoader
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)

.build();
ImageLoader.getInstance().init(config);

ImageLoaderConfiguration
ImageLoader的配置参数——ImageLoaderConfiguration 对Application来说是全局的,你只能设置一次。

所有关于Configuration builder中的配置选项都是可选的,使用你真实需要的选项来进行配置。

可以如下文档来查看各个选项的默认值:

ImageLoaderConfiguration.java

//不要将这段代码拷贝进你的工程。这仅仅是所有配置选项使用的范例。
// 查看sample工程来学习如何正确的使用ImageLoader

//这里的路径可以自定义
File cacheDir = StorageUtils.getCacheDirectory(context);

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
// 默认等于你的屏幕尺寸,设备屏幕宽高
.memoryCacheExtraOptions(480, 800)
// 在将下载的图片保存到你的sd卡之前会重新计算,压缩。
// 这个属性不要滥用,只有你在对应的需求时再用,因为他会使你的ImageLoader变的很慢。
.diskCacheExtraOptions(480, 800, null)
//用于执行从源获取图片任务的 Executor,为configuration中的 taskExecutor,
// 如果为null,则会调用DefaultConfigurationFactory.createExecutor(…)根据配置返回一个默认的线程池。
.taskExecutor(null)
//用于执行从缓存获取图片任务的 Executor,为configuration中的 taskExecutorForCachedImages,
// 如果为null,则会调用DefaultConfigurationFactory.createExecutor(…)根据配置返回一个默认的线程池。
.taskExecutorForCachedImages(null)
// 表示核心池大小(*大并发数) 默认为3
.threadPoolSize(3)
// 线程优先级,默认Thread.NORM_PRIORITY – 2
.threadPriority(Thread.NORM_PRIORITY – 2)
// 任务进程的顺序,默认为:FIFO 先进先出
.tasksProcessingOrder(QueueProcessingType.FIFO)
//设置内存缓存不允许缓存一张图片的多个尺寸,默认允许。
.denyCacheImageMultipleSizesInMemory()
//图片内存缓存
.memoryCache(new LruMemoryCache(2 * 1024 * 1024))
//memoryCacheSize 为 0,则设置该内存缓存的*大字节数为 App *大可用内存的 1/8。
.memoryCacheSize(2 * 1024 * 1024)
// 创建*大的内存缓存百分比,默认为 13%
.memoryCacheSizePercentage(13)
// 硬盘缓存路径,默认为StorageUtils.getCacheDirectory(context)
.diskCache(new UnlimitedDiskCache(cacheDir))
//硬盘缓存大小
.diskCacheSize(50 * 1024 * 1024)
//缓存文件数量
.diskCacheFileCount(100)
// 硬盘缓存文件名生成器,默认为哈希文件名生成器
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
// 创建图片下载器,默认是BaseImageDownloader
.imageDownloader(new BaseImageDownloader(context))
// 图片解码器,负责将图片输入流InputStream转换为Bitmap对象
.imageDecoder(new BaseImageDecoder(true))
// 图片显示的配置项。比如加载前、加载中、加载失败应该显示的占位图片,图片是否需要在磁盘缓存,是否需要在内存缓存等。
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
//是否显示调试log信息
.writeDebugLogs()
.build();

ImageLoader.getInstance().init(config);

以上是官方文档的写法,下面对这写配置进行讲解,并且给出,我认为的比较合理的写法。

我所推荐的写法:

ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
config.threadPriority(Thread.NORM_PRIORITY – 2);
config.denyCacheImageMultipleSizesInMemory();
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.tasksProcessingOrder(QueueProcessingType.LIFO);
config.diskCache(new UnlimitedDiskCache(new File(Environment.getExternalStorageDirectory()+”/target”)));

if (BuildConfig.DEBUG){
config.writeDebugLogs(); // 发布release包时,移除log信息 }

// 用configuration初始化ImageLoader ImageLoader.getInstance().init(config.build());

这里主要是想为你展示:

if (BuildConfig.DEBUG){
config.writeDebugLogs(); // Remove for release app
}

在我们发布release包时,需要屏蔽UIL中的log信息,上述代码可以做到。

Display Options
Display Options (DisplayImageOptions)对于每一个展示任务都可以使用

ImageLoader.displayImage(…)

注意:

如果没有给ImageLoader.displayImage(xxx)这个方法传递Display Options,那么这个方法将会使用默认的Display Options ,

ImageLoaderConfiguration.defaultDisplayImageOptions(…)

DisplayImageOptions options = new DisplayImageOptions.Builder()
// 正在加载时显示的占位图
.showImageOnLoading(R.drawable.ic_stub)
// URL为空时显示的占位图
.showImageForEmptyUri(R.drawable.ic_empty)
// 加载失败时显示的占位图
.showImageOnFail(R.drawable.ic_error)
// 在加载前是否重置 view,默认为false
.resetViewBeforeLoading(false)
//设置在开始加载前的延迟时间,单位为毫秒,通过 Builder 构建的对象默认为 0
.delayBeforeLoading(1000)
// 是否缓存在内存中,通过 Builder 构建的对象默认为 false
.cacheInMemory(false)
// 是否缓存在磁盘中,通过 Builder 构建的对象默认为 false。
.cacheOnDisk(false)
//缓存在内存之前的处理程序,默认为 null
.preProcessor(null)
//缓存在内存之后的处理程序,默认为 null。
.postProcessor(null)
//下载器需要的辅助信息。下载时传入ImageDownloader.getStream(String, Object)的对象,方便用户自己扩展,默认为 null。
.extraForDownloader(null)
// 是否考虑图片的 EXIF 信息,通过 Builder 构建的对象默认为 false。
.considerExifParams(false)
// 图片的缩放类型,通过 Builder 构建的对象默认为IN_SAMPLE_POWER_OF_2
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
// bitmap的质量,默认为ARGB_8888
.bitmapConfig(Bitmap.Config.ARGB_8888)
//为 BitmapFactory.Options,用于BitmapFactory.decodeStream(imageStream, null, decodingOptions)得到图片尺寸等信息。
.decodingOptions(null)
// 在ImageAware中显示 bitmap 对象的接口。可在实现中对 bitmap 做一些额外处理,比如加圆角、动画效果。
.displayer(new SimpleBitmapDisplayer())
// handler 对象,默认为 null
.handler(new Handler())
.build();

注意

千万不要把这段代码整体拷贝如你的工程。这仅仅是所有选项的示例。查看实例工程来学习ImageLoader 中 DisplayImageOptions 的正确用法。

可支持的格式:
http , file , content, assets , drawable , https

“http://site.com/image.png” // from Web
“file:///mnt/sdcard/image.png” // from SD card
“file:///mnt/sdcard/video.mp4” // from SD card (video thumbnail)
“content://media/external/images/media/13” // from content provider
“content://media/external/video/media/13” // from content provider (video thumbnail)
“assets://image.png” // from assets
“drawable://” + R.drawable.img // from drawables (non-9patch images)
“https://www.eff.org/sites/default/files/chrome150_0.jpg”,//Image from HTTPS

注意:
如果你真的需要使用drawable:// ,*好还是用Native加载drawable方式,ImageView.setImageResource(….)而不是使用ImageLoader.

Library Map
Library Map

Useful Info
Useful Info

User Support
User Support

上述只是,对官方Wiki的一个简单整理,对于UIL的使用实例,我将在Demo中给出!

使用实例:

UILExample
建议您参考,官方demo
————————————————

[Android] ImageView.ScaleType设置图解

ImageView的Scaletype决定了图片在View上显示时的样子,如进行何种比例的缩放,及显示图片的整体还是部分,等等。

设置的方式包括:

1. 在layout xml中定义android:scaleType=”CENTER”

2. 或在代码中调用imageView.setScaleType(ImageView.ScaleType.CENTER);

接下来,将对ScaleType的值和对应的显示效果用*直观的方式——真图演示的方法,来进行说明。

首先,是测试使用的原始图片:

%title插图%num(Dimensions: 128 * 128)

%title插图%num (Dimensions: 640 * 428)

好,开始下面的测试:

1. SetScaleType(ImageView.ScaleType.CENTER);

按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

%title插图%num               %title插图%num

2. SetScaleType(ImageView.ScaleType.CENTER_CROP);

按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)

%title插图%num               %title插图%num

3. setScaleType(ImageView.ScaleType.CENTER_INSIDE);

将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽

%title插图%num               %title插图%num

4. setScaleType(ImageView.ScaleType.FIT_CENTER);

把图片按比例扩大/缩小到View的宽度,居中显示

%title插图%num               %title插图%num

5. FIT_START, FIT_END在图片缩放效果上与FIT_CENTER一样,只是显示的位置不同,FIT_START是置于顶部,FIT_CENTER居中,FIT_END置于底部。

在此就不给出示例了。

6. FIT_XY

不按比例缩放图片,目标是把图片塞满整个View。

%title插图%num               %title插图%num

Imageloader 配合image中的属性 显示缩略图

1、 昨天用imageloader做的图片异步加载,后来发现有个问题,图片的缩略图不正常,只显示图片的局部而不是整体的缩略图,体验很差,后俩经过多次修改,查询了imageloader的多种方法,
*后使用 imageLoader .loadImage,发现使用 imageLoader.displayImage就不行
ImageSize size= new  ImageSize(100, 100);
//imageLoader.displayImage(path, holder.imageView, options, animateFirstListener);
imageLoader .loadImage(path, size,  new  ImageLoadingListener() {

@Override
public  void  onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
//  TODO  Auto-generated method stub
holder.  imageView .setImageBitmap(loadedImage);
}
*后配合ImageView的属性android:scaleType使用了fitxy搞定!(图像会失真),*后发现图库是采用的中间部分压缩作为缩略图的。
imageView.setScaleType(ImageView.ScaleType.FIT_XY );
1 这里我们重点理解ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType)。android:scaleType是控制图片如何resized/moved来匹对ImageView的size。ImageView.ScaleType / android:scaleType值的意义区别:
2
3 CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
4
5 CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
6
7 CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
8
9 FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
10
11 FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
12
13 FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
14
15 FIT_XY / fitXY 把图片不按比例扩大/缩小到View的大小显示
16
17 MATRIX / matrix 用矩阵来绘制

一开始我不明白MATRIX矩阵,网上搜索后发现原来MATRIX矩阵可以动态缩小放大图片来显示,这里不展开深入的了解,只是贴出相关语句,缩小图片:

1 //获得Bitmap的高和宽
2 int bmpWidth=bmp.getWidth();
3 int bmpHeight=bmp.getHeight();
4
5 //设置缩小比例
6 double scale=0.8;
7 //计算出这次要缩小的比例
8 scaleWidth=(float)(scaleWidth*scale);
9 scaleHeight=(float)(scaleHeight*scale);
10
11 //产生resize后的Bitmap对象
12 Matrix matrix=new Matrix();
13 matrix.postScale(scaleWidth, scaleHeight);
14 Bitmap resizeBmp=Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, true);
1 <ImageView
2 android:id=”@+id/image”
3 android:layout_width=”fill_parent”
4 android:layout_height=”fill_parent”
5 android:scaleType=”center”
6 android:src=”@drawable/candle”
7 />

ImageLoader.getInstance().displayImage(avatar, iv_recent_avatar, ImageLoadOptions.getOptions());
在独立的adapter中直接使用imageloader 需要将ImageLoadOptions初始化操作写为一个独立的类
————————————————

Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration

一、介绍

Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。所以,如果你的程序里需要这个功能的话,那么不妨试试它。因为已经封装好了一些类和方法。我们 可以直接拿来用了。而不用重复去写了。其实,写一个这方面的程序还是比较麻烦的,要考虑多线程缓存,内存溢出等很多方面。

二、具体使用

一个好的类库的重要特征就是可配置性强。我们先简单使用Android-Universal-Image-Loader,一般情况下使用默认配置就可以了。

下面的实例利用Android-Universal-Image-Loader将网络图片加载到图片墙中。

 1 public class BaseActivity extends Activity {
 2     ImageLoader imageLoader;
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5           // Create global configuration and initialize ImageLoader with this configuration
 6         ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
 7             .build();
 8         ImageLoader.getInstance().init(config);
 9         super.onCreate(savedInstanceState);
10     }
11 }
  1 public class MainActivity extends BaseActivity {
  2 
  3     @Override
  4     protected void onCreate(Bundle savedInstanceState) {
  5         super.onCreate(savedInstanceState);
  6         setContentView(R.layout.activity_main);
  7   
  8         ImageLoader imageLoader = ImageLoader.getInstance();
  9 
 10         GridView gridView = (GridView) this.findViewById(R.id.grdvImageWall);
 11         gridView.setAdapter(new PhotoWallAdapter(Constants.IMAGES));
 12     }
 13 
 14     static class ViewHolder {
 15         ImageView imageView;
 16         ProgressBar progressBar;
 17     }
 18 
 19     public class PhotoWallAdapter extends BaseAdapter {
 20         String[] imageUrls;
 21         ImageLoader imageLoad;
 22         DisplayImageOptions options;
 23         LinearLayout gridViewItem;
 24 
 25         public PhotoWallAdapter(String[] imageUrls) {
 26             assert imageUrls != null;
 27             this.imageUrls = imageUrls;
 28 
 29             options = new DisplayImageOptions.Builder()
 30                     .showImageOnLoading(R.drawable.ic_stub) // resource or
 31                                                             // drawable
 32                     .showImageForEmptyUri(R.drawable.ic_empty) // resource or
 33                                                                 // drawable
 34                     .showImageOnFail(R.drawable.ic_error) // resource or
 35                                                             // drawable
 36                     .resetViewBeforeLoading(false) // default
 37                     .delayBeforeLoading(1000).cacheInMemory(false) // default
 38                     .cacheOnDisk(false) // default
 39                     .considerExifParams(false) // default
 40                     .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
 41                     .bitmapConfig(Bitmap.Config.ARGB_8888) // default
 42                     .displayer(new SimpleBitmapDisplayer()) // default
 43                     .handler(new Handler()) // default
 44                     .build();
 45             this.imageLoad = ImageLoader.getInstance();
 46 
 47         }
 48 
 49         @Override
 50         public int getCount() {
 51             return this.imageUrls.length;
 52         }
 53 
 54         @Override
 55         public Object getItem(int position) {
 56             if (position <= 0 || position >= this.imageUrls.length) {
 57                 throw new IllegalArgumentException(
 58                         "position<=0||position>=this.imageUrls.length");
 59             }
 60             return this.imageUrls[position];
 61         }
 62 
 63         @Override
 64         public long getItemId(int position) {
 65             return position;
 66         }
 67 
 68         @Override
 69         public View getView(int position, View convertView, ViewGroup parent) {
 70             // 判断这个image是否已经在缓存当中,如果没有就下载
 71             final ViewHolder holder;
 72             if (convertView == null) {
 73                 holder = new ViewHolder();
 74                 gridViewItem = (LinearLayout) getLayoutInflater().inflate(
 75                         R.layout.image_wall_item, null);
 76                 holder.imageView = (ImageView) gridViewItem
 77                         .findViewById(R.id.item_image);
 78                 holder.progressBar = (ProgressBar) gridViewItem
 79                         .findViewById(R.id.item_process);
 80                 gridViewItem.setTag(holder);
 81                 convertView = gridViewItem;
 82             } else {
 83                 holder = (ViewHolder) gridViewItem.getTag();
 84             }
 85             this.imageLoad.displayImage(this.imageUrls[position],
 86                     holder.imageView, options,
 87                     new SimpleImageLoadingListener() {
 88 
 89                         @Override
 90                         public void onLoadingStarted(String imageUri, View view) {
 91                             holder.progressBar.setProgress(0);
 92                             holder.progressBar.setVisibility(View.VISIBLE);
 93                         }
 94 
 95                         @Override
 96                         public void onLoadingFailed(String imageUri, View view,
 97                                 FailReason failReason) {
 98                             holder.progressBar.setVisibility(View.GONE);
 99                         }
100 
101                         @Override
102                         public void onLoadingComplete(String imageUri,
103                                 View view, Bitmap loadedImage) {
104                             holder.progressBar.setVisibility(View.GONE);
105                         }
106 
107                     }, new ImageLoadingProgressListener() {
108 
109                         @Override
110                         public void onProgressUpdate(String imageUri,
111                                 View view, int current, int total) {
112                             holder.progressBar.setProgress(Math.round(100.0f
113                                     * current / total));
114                         }
115                     }); // 通过URL判断图片是否已经下载
116             return convertView;
117         }
118 
119     }
120 }

里面主要的对象都用        突出显示了。

三者的关系

ImageLoaderConfiguration是针对图片缓存的全局配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

ImageLoader是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(…)、loadImage(…),但是其实*终他们的实现都是displayImage(…)。

DisplayImageOptions用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理。

从三者的协作关系上看,他们有点像厨房规定、厨师、客户个人口味之间的关系。ImageLoaderConfiguration就像是厨房里面的规定,每一个厨师要怎么着装,要怎么保持厨房的干净,这是针对每一个厨师都适用的规定,而且不允许个性化改变。ImageLoader就像是具体做菜的厨师,负责具体菜谱的制作。DisplayImageOptions就像每个客户的偏好,根据客户是重口味还是清淡,每一个imageLoader根据DisplayImageOptions的要求具体执行。

 

ImageLoaderConfiguration

在上面的示例代码中,我们使用ImageLoaderConfiguration的默认配置,下面给出ImageLoaderConfiguration比较详尽的配置,从下面的配置中,可以看出ImageLoaderConfiguration的配置主要是全局性的配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
        .diskCacheExtraOptions(480, 800, null)
        .taskExecutor(...)
        .taskExecutorForCachedImages(...)
        .threadPoolSize(3) // default
        .threadPriority(Thread.NORM_PRIORITY - 1) // default
        .tasksProcessingOrder(QueueProcessingType.FIFO) // default
        .denyCacheImageMultipleSizesInMemory()
        .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
        .memoryCacheSize(2 * 1024 * 1024)
        .memoryCacheSizePercentage(13) // default
        .diskCache(new UnlimitedDiscCache(cacheDir)) // default
        .diskCacheSize(50 * 1024 * 1024)
        .diskCacheFileCount(100)
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
        .imageDownloader(new BaseImageDownloader(context)) // default
        .imageDecoder(new BaseImageDecoder()) // default
        .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
        .writeDebugLogs()
        .build();

ImageLoaderConfiguration的主要职责就是记录相关的配置,它的内部其实就是一些字段的集合(如下面的源代码)。它有一个builder的内部类,这个类中的字段跟ImageLoaderConfiguration中的字段完全一致,它有一些默认值,通过修改builder可以配置ImageLoaderConfiguration。

%title插图%num View Code

 

 Display Options

每一个ImageLoader.displayImage(...)都可以使用Display Options

DisplayImageOptions options = new DisplayImageOptions.Builder()
        .showImageOnLoading(R.drawable.ic_stub) // resource or drawable
        .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable
        .showImageOnFail(R.drawable.ic_error) // resource or drawable
        .resetViewBeforeLoading(false)  // default
        .delayBeforeLoading(1000)
        .cacheInMemory(false) // default
        .cacheOnDisk(false) // default
        .preProcessor(...)
        .postProcessor(...)
        .extraForDownloader(...)
        .considerExifParams(false) // default
        .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
        .bitmapConfig(Bitmap.Config.ARGB_8888) // default
        .decodingOptions(...)
        .displayer(new SimpleBitmapDisplayer()) // default
        .handler(new Handler()) // default
        .build();

Display Options的主要职责就是记录相关的配置,它的内部其实就是一些字段的集合(如下面的源代码)。它有一个builder的内部类,这个类中的字段跟DisplayOption中的字段完全一致,它有一些默认值,通过修改builder可以配置DisplayOptions。

%title插图%num View Code

 

 

 

Android-Universal-Image-Loader 配置UIL配置

ImageLoaderConfiguration

在上面的示例代码中,我们使用ImageLoaderConfiguration的默认配置,下面给出ImageLoaderConfiguration比较详尽的配置,从下面的配置中,可以看出ImageLoaderConfiguration的配置主要是全局性的配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
        .memoryCacheExtraOptions(480, 800) // default = device screen dimensions
        .diskCacheExtraOptions(480, 800, null)
        .taskExecutor(...)
        .taskExecutorForCachedImages(...)
        .threadPoolSize(3) // default
        .threadPriority(Thread.NORM_PRIORITY - 1) // default
        .tasksProcessingOrder(QueueProcessingType.FIFO) // default
        .denyCacheImageMultipleSizesInMemory()
        .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
        .memoryCacheSize(2 * 1024 * 1024)
        .memoryCacheSizePercentage(13) // default
        .diskCache(new UnlimitedDiscCache(cacheDir)) // default
        .diskCacheSize(50 * 1024 * 1024)
        .diskCacheFileCount(100)
        .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
        .imageDownloader(new BaseImageDownloader(context)) // default
        .imageDecoder(new BaseImageDecoder()) // default
        .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
        .writeDebugLogs()
        .build();

 

Display Options

每一个ImageLoader.displayImage(…)都可以使用Display Options。

DisplayImageOptions options = new DisplayImageOptions.Builder()
        .showImageOnLoading(R.drawable.ic_stub) // resource or drawable
        .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable
        .showImageOnFail(R.drawable.ic_error) // resource or drawable
        .resetViewBeforeLoading(false)  // default
        .delayBeforeLoading(1000)
        .cacheInMemory(false) // default
        .cacheOnDisk(false) // default
        .preProcessor(...)
        .postProcessor(...)
        .extraForDownloader(...)
        .considerExifParams(false) // default
        .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
        .bitmapConfig(Bitmap.Config.ARGB_8888) // default
        .decodingOptions(...)
        .displayer(new SimpleBitmapDisplayer()) // default
        .handler(new Handler()) // default
        .build();

 

ImageView的scaleType的属性理解

ImageView的scaleType的属性值有MATRIX,FIT_XY,FIT_START,FIT_END,FIT_CENTER,CENTER,CENTER_CROP,CENTER_INSIDE.

1.android:scaleType=“center”
保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size时,多出来的部分被截掉。
2.android:scaleType=“center_inside”
以原图正常显示为目的,如果原图大小大于ImageView的size,就按照比例缩小原图的宽高,居中显示在ImageView中。如果原图size小于ImageView的size,则不做处理居中显示图片。
3.android:scaleType=“center_crop”
以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示。
4.android:scaleType=“matrix”
不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理。
5.androd:scaleType=“fit_xy”
把图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例,填满ImageView.
6.android:scaleType=“fit_start”
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的start(前部/上部)。
7.android:sacleType=“fit_center”
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的center(中部/居中显示)。
8.android:scaleType=“fit_end”
把原图按照比例放大缩小到ImageView的高度,显示在ImageVIew的end(后部/尾部/底部)

这里写图片描述

 

513.找树左下角的值 Python DFS 、BFS双解!

513.找树左下角的值 Python DFS 、BFS双解!
一个优秀的内容风控解决方案应该是怎样的?
信息传播的媒介与形态五花八门,对于互联网平台来说,保障内容安全越来越难。当下互联网平台面临哪些困境?7月3日,腾讯安全思享会,带大家一起探索亟需的答案,限额报名
513.找树左下角的值
https://leetcode-cn.com/problems/find-bottom-left-tree-value/
难度:中等
题目:
给定一个二叉树,在树的*后一行找到*左边的值。
示例:
示例 1:
输入:
    2
   / \
  1   3
输出:
1
示例 2:
输入:
        1
       / \
      2   3
     /   / \
    4   5   6
       /
      7
输出:
7
分析
这虽然是一道中等题,但讲真的难度比较一般…
首先,*简单的应该是BFS逐层遍历
我们创建一个空列表,用于记录每行的*个val
然后创建一个队列,root入队,开始while循环
每行的*个节点入队,判断*个方式为比较index与列表的长度是否相等
知道队列为空时,终止循环,pop列表*后一个数值即可。
那么,这道题用DFS同样很简单
为了练习,这次我们使用一个字典保存
同样的递归遍历左子树和右子树
判断字典中是否包含该值,然后插入该值
由于是数字hash,所以其实是有序的,直接values.pop()即可。
解题-BFS:
from collections import deque
class Solution:
    def findBottomLeftValue(self, root):
        li, queue= [], deque([[root, 1]])
        while queue:
            for _ in range(len(queue)):
                child, index = queue.popleft()
                if len(li) < index:
                    li.append(child.val)
                index += 1
                if child.left:
                    queue.append([child.left, index])
                if child.right:
                    queue.append([child.right, index])
        return li.pop()
解题-DFS:
class Solution:
    def findBottomLeftValue(self, root):
        d = {}
        def dfs(child, index):
            if not child:
                return
            if index not in d:
                d[index] = child.val
            dfs(child.left, index + 1)
            dfs(child.right, index + 1)
        dfs(root, 1)
        return list(d.values()).pop()

374.猜数字大小 python二分查找的基础公式!

374.猜数字大小 python二分查找的基础公式!
一个优秀的内容风控解决方案应该是怎样的?
信息传播的媒介与形态五花八门,对于互联网平台来说,保障内容安全越来越难。当下互联网平台面临哪些困境?7月3日,腾讯安全思享会,带大家一起探索亟需的答案,限额报名
374.猜数字大小
https://leetcode-cn.com/problems/guess-number-higher-or-lower/solution/374cai-shu-zi-da-xiao-pythoner-fen-cha-z-6b8x/
难度:简单
题目:
猜数字游戏的规则如下:
每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
-1:我选出的数字比你猜的数字小 pick < num
1:我选出的数字比你猜的数字大 pick > num
0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字。
示例:
示例 1:
输入:n = 10, pick = 6
输出:6
示例 2:
输入:n = 1, pick = 1
输出:1
分析
今天这道每日一题,比昨天的:
278.*个错误的版本
要更简单一些,是一个标准的二分查找target。虽然这道题的中文翻译实在是有些逗比…
然后看看官方解题,解决不知道是套公式套的死板还是怎样?
以下是官方解题:
class Solution:
    def guessNumber(self, n: int) -> int:
        left, right = 1, n
        while left < right:
            mid = (left + right) // 2
            if guess(mid) <= 0:
                right = mid   # 答案在区间 [left, mid] 中
            else:
                left = mid + 1   # 答案在区间 [mid+1, right] 中
        # 此时有 left == right,区间缩为一个点,即为答案
        return left
搞不懂,既然guess结果为0,即找到target了,不退出循环,还在那里缩小什么范围?
就是为了让你的代码看着能少一层判断,“显得”更为简洁吗?
解题:
class Solution:
    def guessNumber(self, n: int) -> int:
        left = 1
        right = n
        while left <= right:
            mid = (left + right) // 2
            ret = guess(mid)
            if ret == 0:
                return mid
            elif ret == -1:
                right = mid – 1
            else:
                left = mid + 1

852.山脉数组的峰顶索引 喜迎收假,重拳出击….

852.山脉数组的峰顶索引 喜迎收假,重拳出击….
852.山脉数组的峰顶索引
https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/solution/852shan-mai-shu-zu-de-feng-ding-suo-yin-9krsr/
难度:简单
题目:
符合下列属性的数组 arr 称为 山脉数组 :
arr.length >= 3
存在 i(0 < i < arr.length – 1)使得:
arr[0] < arr[1] < … arr[i-1] < arr[i]
arr[i] > arr[i+1] > … > arr[arr.length – 1]
给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < … arr[i – 1] < arr[i] > arr[i + 1] > … > arr[arr.length – 1] 的下标 i 。
提示:
3 <= arr.length <= 104
0 <= arr[i] <= 10 ^ 6
题目数据保证 arr 是一个山脉数组
示例:
示例 1:
输入:arr = [0,1,0]
输出:1
示例 2:
输入:arr = [0,2,1,0]
输出:1
示例 3:
输入:arr = [0,10,5,2]
输出:1
示例 4:
输入:arr = [3,4,5,1]
输出:2
示例 5:
输入:arr = [24,69,100,99,79,78,67,36,26,19]
输出:2
分析
既然题目保证存在一个山脉数组,那么不就是让我们找到:
arr[i] > arr[i – 1] and arr[i] > arr[i + 1]吗?
循环或者直接求*大值即可
解题:
class Solution:
    def peakIndexInMountainArray(self, arr):
        for i in range(1, len(arr) – 1):
            if arr[i – 1]  < arr[i] and arr[i] > arr[i + 1] :
                return i
class Solution:
    def peakIndexInMountainArray(self, arr):
        return arr.index(max(arr))
友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速