首页 文章 精选 留言 我的

精选列表

搜索[android jetpack],共10000篇文章
优秀的个人博客,低调大师

Android探究事件分发

以前没太注意,很久没用之后再使用发现有些地方模糊了,就是那种不知道是对是错的感觉,然后又要重复上网去找资料,所以打算自己整理一篇,有很多时候,一些特殊的需要要是能巧妙的运用事件分发机制其实能很快的去解决问题。 一.流程 1.打印全流程 对于activity,viewgroup和view来说,如果不再任意一个流程消费事件,就会打印出这个结果。 image.png 这个就不用多解释了,如果都没消费事件,会在最后一句打印出ACTION_DOWN没有被处理。 2.图解过程 由上面打印的过程可以做出下面一张事件分发时的流程图: image.png 但是在activity,viewgroup和view的dispatchTouchEvent、onTouchEvent这些方法中,返回值是一个布尔类型的,有三种情况,false,true和super,分别对这三种情况和分发流程进行探究后得到下图: image.png 图太麻烦了,我就不重新画了,从网上找了一张,不同的是,图中的onTouchEvent,我试过,如果传的是super,是会被消费的,而不是返回上一层。 3.一般情况下的事件分发 上面的情况我是重写viewgroup重写view去重写onTouchEvent和dispatchTouchEvent方法,但是实际操作中不会总是这种情况,因为我们不可能把接触到事件分发需求的控件都重写,那样就太麻烦了。所以先来看看一般情况下的分发情况。 我把自定义view换成普通的view然后写onClick方法,打印以下结果 image.png 发现在onClick事件中,view会消费事件,即便你在onClick中没做什么操作,事件也会被view给消费,那不写onClick方法呢? image.png 发现打印结果中,即便没对View监听,事件也不会往上传,然后我打算看看view中的源码 image.png 我* , 看来我本地是看不了了,别的地方找找。如果你看到了源码,你会发现卧槽真尼玛多,一大堆判断。我就找来了一个别人整理过的所写版的。感谢这位大神,很有良心。 if (((viewFlags & CLICKABLE) == CLICKABLE ||(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) { switch (action) { case MotionEvent.ACTION_UP: boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { ... if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { // This is a tap, so remove the longpress check removeLongPressCallback(); // Only perform take click actions if we were in the pressed state if (!focusTaken) { // Use a Runnable and post this rather than calling // performClick directly. This lets other visual state // of the view update before click actions start. if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); } } } ... break; ... } return true; } 看得出默认的情况下,返回true也就是被消费。我看了源码就知道了,当然没贴出来,这里设置setClickable的话就会有神奇的效果,我设置view.setClickable(false); 打印出下面的结果。 image.png 所以能得出一个简单的结论,一般情况下你不从写view,要让这个view的事件往上层分发,需要设置setClickable(false) 那有的朋友说,我要有那种点击view之后,view先做操作,然后viewgroup在做操作,而且还不是自定义view和viewgrou的条件下。如果是直接对View设置onClickListener的话是无法达到这个效果的,所以只能对view设置OnTouchListener btnContent.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { Log.v("mmp", "view->setOnTouchListener"); } return false; } }); 这样就能先执行view的点击事件,再执行viewgroup的点击事件。 image.png 4.总结 事件分发有意思的地方就在于,你想让什么去触发这个事件,并且是否分发给上一层去做处理,更有意思的地方在于这个机制是先向下分发,由activity分发给viewgroup再分发给view,之后执行是向上执行,先由view执行。所以它使用起来会很灵活,比如说你想做一系列的点击事件,点击一个按钮后activity先执行某步操作,view再执行某步操作,然后activity再执行某部操作,这个做法也是可以做到的。 二.事件分发的灵活用法 事件分发他是一个机制,所以它可以适用于很多的场景,不要说它只能用于处理特殊的点击事件,那可真是暴殄天物。 1.防止快速点击 我们可以用事件分发机制来防止快速点击,如果对一个按钮就行快速点击那就会出现很糟糕的后果,所以一般的app中又要做防止快速点击的操作,有些人对一些按钮重复进行快速点击的操作,那就很浪费时间,可以直接在activity中做处理。 重写activity的dispatchTouchEvent方法,记录最后一次触发点击事件的事件,每次点击都获取时间,如果两个时间相减小于XXX秒,就返回true,这样快速点击的时候事件就不会分发下去,大于这个时间就返回super。 在activity中写 @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if (System.currentTimeMillis() - lastTime < 500) { return true; } } return super.dispatchTouchEvent(ev); } 当然除了这样子做之外,你也可以自己写个根布局,然后所有xml中的布局都写这个根布局,再用viewgroup的onInterceptTouchEvent来拦截也行。 2.仿dialog点击外部内容消失效果 我也是因为这个需求所以才想写这个文章大,假如我要做一个图层,实现在recyclerview的item中弹出的效果,对item的弹框效果的图层,如果你是用一种图层的思想你就知道这个图层应该是做在item上,activity下,所以无法使用dialog或popupwindow,因为这两个弹框都是顶层的图层,所以只能加一层布局来显示和隐藏达到效果。而要实现这个效果,可以在activity的dispatchTouchEvent中加判断。

优秀的个人博客,低调大师

Android -- getWidth()与getMeasuredWidth()

getWidth() Return the width of the your view. Returns The width of your view, in pixels. 源代码: public final int getWidth() { return mRight - mLeft; } getwidth返回的是右边坐标减轻坐标减去左边坐标,这要在布局之后才能确定它们的坐标,也就是说在布局后才能调用getwidth来获取。所以getWidth()获得的宽度是View在设定好布局后整个View的宽度。 getMeasuredWidth() Return the full width measurement information for this view as computed by the most recent call to measure(int, int). This result is a bit mask as defined byMEASURED_SIZE_MASK and MEASURED_STATE_TOO_SMALL. This should be used during measurement and layout calculations only. Use getWidth() to see how wide a view is after layout. Returns The measured width of this view as a bit mask. 得到的是最近一次调用measure()方法测量后得到的是View的宽度,它应该仅仅用在测量和Layout的计算中。再看源码: public final int getMeasuredWidth() { return mMeasuredWidth & MEASURED_SIZE_MASK; } return Therawmeasured width of this view 获得的是原始的测量宽度。所以说getMeasuredWidth()是对View上的内容进行测量后得到的View内容占据的宽度。前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);(measure中的参数的值你自己可以定义),否则你得到的结果和getWidth()得到的结果是一样的。 区别 getMeasuredWidth:对View上的内容进行测量后得到的View内容占据的宽度的。 getWidth:View在设定号布局后整个View的宽度。 使用场合 getMeasuredWidth:在自定义view重写onLayout时、在我们用layoutinflater动态加载view后想获得view的原始宽度时。 getWidth:一般在view已经布局后呈现出来了,想获取宽度时。 我是天王盖地虎的分割线 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/4783652.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android -- ImageLoader简析

图片的内存缓存实现 Image-Loader库有一个较完整的内存缓存实现,使用者可以根据需要选择已经实现的策略,也可以定制自己项目中需要的策略。 内存缓存实现代码在memory和memory.impl这两个包中,前者就是规范视图,后者是实现视图。memory包中有MemoryCacheAware接口和BaseMemoryCache和LimitedMemoryCache两个抽象类,加上memory.impl包中的WeakMemoryCache类。 MemoryCacheAware MemoryCacheAware接口以泛型方式定义了实现缓存所需的基础规约,包括写缓存、读缓存、删除缓存和遍历缓存等: /** * Interface for memory cache * * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) * @since 1.0.0 */ public interface MemoryCacheAware<K, V> { /** * Puts value into cache by key * * @return <b>true</b> - if value was put into cache successfully, <b>false</b> - if value was <b>not</b> put into * cache */ boolean put(K key, V value); /** Returns value by key. If there is no value for key then null will be returned. */ V get(K key); /** Removes item by key */ void remove(K key); /** Returns all keys of cache */ Collection<K> keys(); /** Remove all items from cache */ void clear(); } 内存缓存依然使用哈希表来实现: /** Stores not strong references to objects */ private final Map<K, Reference<V>> softMap = Collections.synchronizedMap(new HashMap<K, Reference<V>>()); BaseMemoryCache implements MemoryCacheAware /** * Base memory cache. Implements common functionality for memory cache. Provides object references ( * {@linkplain Reference not strong}) storing. * * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) * @since 1.0.0 */ public abstract class BaseMemoryCache<K, V> implements MemoryCacheAware<K, V> { /** Stores not strong references to objects */ private final Map<K, Reference<V>> softMap = Collections.synchronizedMap(new HashMap<K, Reference<V>>()); @Override public V get(K key) { V result = null; Reference<V> reference = softMap.get(key); if (reference != null) { result = reference.get(); } return result; } @Override public boolean put(K key, V value) { softMap.put(key, createReference(value)); return true; } @Override public void remove(K key) { softMap.remove(key); } @Override public Collection<K> keys() { synchronized (softMap) { return new HashSet<K>(softMap.keySet()); } } @Override public void clear() { softMap.clear(); } /** Creates {@linkplain Reference not strong} reference of value */ protected abstract Reference<V> createReference(V value); } 基本上就是HashMap的操作,由于具体Reference的实现需要看到底用的哪种引用,因此,这里将createReference定义成抽象函数,让BaseMemoryCache的子类去定制实现。 WeakMemoryCache extends BaseMemoryCache BaseMemoryCache的一个最简单的子类实现是WeakMemoryCache类,它仅仅是实现了createReference抽象方法,返回Bitmap对象的弱引用: public class WeakMemoryCache extends BaseMemoryCache<String, Bitmap> { @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); } } LimitedMemoryCache extends BaseMemoryCache BaseMemoryCache的另一个子类是LimitedMemoryCache,它也是抽象类,定义了实现内存缓存限制策略的公共操作。既然要限制缓存大小,那么首先需要定义默认的缓存最大值,同时需要维护一个表示当前缓存已占用大小的变量,考虑到多线程问题,这个变量值得增减必须保证是原子的,因此,该变量类型选用AtomicInteger。如下所示: private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16; private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024; private final int sizeLimit; private final AtomicInteger cacheSize; 同时,为了计算已添加到缓存中的数据大小,需要新增一个指向强引用的数据结构来进行记录,而不是使用BaseMemoryCache中的softMap哈希表,因为softMap中存放的是Reference类,里面的数据可能会被GC回收,用来统计已占用大小时不准确。指向数据强引用的数据结构选用LinkedList,定义如下,同样采用线程安全版本。 /** * Contains strong references to stored objects. Each next object is added last. If hard cache size will exceed * limit then first object is deleted (but it continue exist at {@link #softMap} and can be collected by GC at any * time) */ private final List<V> hardCache = Collections.synchronizedList(new LinkedList<V>()); 往LimitedMemoryCache中添加数据时,首先要计算出当前这个数据的大小(getSize()),然后加上已占用缓存大小后,跟缓存最大值相比较,超过缓存最大值时,就需要根据缓存清理策略(removeNext())删除以前的一些数据,直到添加数据后,总占用大小在最大值之内为止。上面提到的getSize()函数和removeNext函数需要子类定制,所以定义成了抽象函数。这是典型的模板方法模式的应用,模板方法模式定义一个操作中算法的步骤,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。下面的put函数中实现的就是算法的步骤,而getSize()和removeNext()函数则是子类可重定义的特定步骤。相关代码如下所示: @Override public boolean put(K key, V value) { boolean putSuccessfully = false; // Try to add value to hard cache int valueSize = getSize(value); int sizeLimit = getSizeLimit(); int curCacheSize = cacheSize.get(); if (valueSize < sizeLimit) { while (curCacheSize + valueSize > sizeLimit) { V removedValue = removeNext(); if (hardCache.remove(removedValue)) { curCacheSize = cacheSize.addAndGet(-getSize(removedValue)); } } hardCache.add(value); cacheSize.addAndGet(valueSize); putSuccessfully = true; } // Add value to soft cache super.put(key, value); return putSuccessfully; } protected abstract int getSize(V value); protected abstract V removeNext(); FIFOLimitedMemoryCache extends LimitedMemoryCache FIFO算法意思是在缓存超过最大值时,缓存清理策略是将最老的数据清理掉,因此使用队列这样的数据结构就可以很好的实现,在Java中,LinkedList类可以实现这样的功能。 private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>()); 而父类LimitedMemoryCache中也定义了类似的数据结构hardCache专门用于计算缓存的数据大小,只不过它是私有的,子类不能使用。但这样就会造成在FIFOLimitedMemoryCache类中存在两个类似的数据结构,内存占用会变大,事实上,FIFOLimitedMemoryCache中的queue完全可以直接使用父类的hardCache,作者之所以没有直接使用,应该是考虑到代码整体类层次结构清晰的问题,毕竟hardCache专门是用于计算缓存大小的,子类实现方式很多种,很多子类并不需要直接使用hardCache,所以单独一个FIFOLimitedMemoryCache以空间来换取代码结构的清晰也是可以理解的。写缓存和清缓存代码如下: @Override public boolean put(String key, Bitmap value) { if (super.put(key, value)) { queue.add(value); return true; } else { return false; } } @Override public void remove(String key) { Bitmap value = super.get(key); if (value != null) { queue.remove(value); } super.remove(key); } @Override public void clear() { queue.clear(); super.clear(); } 前面说到的父类总共有3个抽象函数,需要子类予以实现,代码如下: @Override protected int getSize(Bitmap value) { return value.getRowBytes() * value.getHeight(); } @Override protected Bitmap removeNext() { return queue.remove(0); } @Override protected Reference<Bitmap> createReference(Bitmap value) { return new WeakReference<Bitmap>(value); } getSize函数中可以看到计算Bitmap占用字节大小的典型方法。removeNext函数中移除队列queue头部的数据,这个数据是最先进入队列的数据。而Bitmap的Reference使用的是弱引用,它和软引用的区别是,弱引用对象拥有更短暂的生命周期,在垃圾回收器线程扫描它所管辖的内存区域过程中,只要发现只具有弱引用的对象,那么不管当前内存空间是否足够,都会回收弱引用对象占用的内存。这样可以更好的防止出现OutOfMemoryError错误。 LargestLimitedMemoryCache extends LimitedMemoryCache 当缓存超出最大值限制时,清理策略是将占用空间最大的数据清理掉。因此,需要一个维护Bitmap对象到它占用大小的映射,这里使用的还是HashMap: /** * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at * {@link #softMap} and can be collected by GC at any time) */ private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>()); 同理,关键代码还是在父类几个抽象函数的实现,其中getSize()和createReference()函数实现和FIFOLimitedMemoryCache类一样,removeNext函数实现如下: @Override protected Bitmap removeNext() { Integer maxSize = null; Bitmap largestValue = null; Set<Entry<Bitmap, Integer>> entries = valueSizes.entrySet(); synchronized (valueSizes) { for (Entry<Bitmap, Integer> entry : entries) { if (largestValue == null) { largestValue = entry.getKey(); maxSize = entry.getValue(); } else { Integer size = entry.getValue(); if (size > maxSize) { maxSize = size; largestValue = entry.getKey(); } } } } valueSizes.remove(largestValue); return largestValue; } 基本原理是遍历valueSizes这个哈希表,比较并得到占用空间最大的Bitmap对象,然后删除它即可。这里要注意的一点是遍历时要加入synchronized同步机制。 LRULimitedMemoryCache extends LimitedMemoryCache LRU即Least Recently Used,缓存清理策略是将最近最少使用的Bitmap对象删除掉。按Java中刚好有这样一个数据结构可以实现这个策略,它就是LinkedHashMap类。 private static final int INITIAL_CAPACITY = 10; private static final float LOAD_FACTOR = 1.1f; /** Cache providing Least-Recently-Used logic */ private final Map<String, Bitmap> lruCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(INITIAL_CAPACITY, LOAD_FACTOR, true)); LinkedHashMap是HashMap的子类,注意它的构造函数第三个参数accessOrder,它定义了LinkedHashMap的排序模式,accessOrder为true时,表示LinkedHashMap中数据排序按照访问的顺序,当为false时,表示数据排序按照数据插入的顺序。而我们要实现LRU,就需要把accessOrder设置为true,同时,在读缓存时不能像FIFOLimitedMemoryCache类和LargestLimitedMemoryCache类一样使用父类BaseMemoryCache的get方法,而是应该重写该方法如下所示: @Override public Bitmap get(String key) { lruCache.get(key); // call "get" for LRU logic return super.get(key); } 当accessOrder设置为true时,LinkedHashMap就维护了记录的访问顺序,这时使用Iterator 遍历LinkedHashMap时,先得到的记录肯定就是最近最不常使用的那个记录了,LRU算法水到渠成: @Override protected Bitmap removeNext() { Bitmap mostLongUsedValue = null; synchronized (lruCache) { Iterator<Entry<String, Bitmap>> it = lruCache.entrySet().iterator(); if (it.hasNext()) { Entry<String, Bitmap> entry = it.next(); mostLongUsedValue = entry.getValue(); it.remove(); } } return mostLongUsedValue; } UsingFreqLimitedMemoryCache extends LimitedMemoryCache 和LargestLimitedMemoryCache类实现类似,只不过一个是将占用空间最大的记录剔除,一个是将访问次数最少的记录剔除,所用数据结构自然类似: /** * Contains strong references to stored objects (keys) and last object usage date (in milliseconds). If hard cache * size will exceed limit then object with the least frequently usage is deleted (but it continue exist at * {@link #softMap} and can be collected by GC at any time) */ private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>()); 因为要记录访问次数,所以需要重写父类的get方法,每访问一次,就增加计数值: @Override public Bitmap get(String key) { Bitmap value = super.get(key); // Increment usage count for value if value is contained in hardCahe if (value != null) { Integer usageCount = usingCounts.get(value); if (usageCount != null) { usingCounts.put(value, usageCount + 1); } } return value; } removeNext函数实现原理是遍历usingCounts哈希表中的记录,比较它们的访问次数,并选取访问次数最少的一个删除之,代码如下所示,同LargestLimitedMemoryCache类,要注意使用synchronized关键字同步保护。 @Override protected Bitmap removeNext() { Integer minUsageCount = null; Bitmap leastUsedValue = null; Set<Entry<Bitmap, Integer>> entries = usingCounts.entrySet(); synchronized (usingCounts) { for (Entry<Bitmap, Integer> entry : entries) { if (leastUsedValue == null) { leastUsedValue = entry.getKey(); minUsageCount = entry.getValue(); } else { Integer lastValueUsage = entry.getValue(); if (lastValueUsage < minUsageCount) { minUsageCount = lastValueUsage; leastUsedValue = entry.getKey(); } } } } usingCounts.remove(leastUsedValue); return leastUsedValue; } FuzzyKeyMemoryCache implements MemoryCacheAware 在之前实现内存缓存的映射时,是一个key对应一个value,而这个装饰者类提供的额外功能是:允许多个key对应同一个value,后面插入的key-value对会覆盖以前存在的key-value对。这个类主要用于Image-Loader库内部使用。在FuzzyKeyMemoryCache类的实现中,使用Comparator类实现多个key是否相等的判断,核心代码在put函数中: /** * Decorator for {@link MemoryCacheAware}. Provides special feature for cache: some different keys are considered as * equals (using {@link Comparator comparator}). And when you try to put some value into cache by key so entries with * "equals" keys will be removed from cache before.<br /> * <b>NOTE:</b> Used for internal needs. Normally you don't need to use this class. * * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) * @since 1.0.0 */ public class FuzzyKeyMemoryCache<K, V> implements MemoryCacheAware<K, V> { private final MemoryCacheAware<K, V> cache; private final Comparator<K> keyComparator; public FuzzyKeyMemoryCache(MemoryCacheAware<K, V> cache, Comparator<K> keyComparator) { this.cache = cache; this.keyComparator = keyComparator; } @Override public boolean put(K key, V value) { // Search equal key and remove this entry synchronized (cache) { K keyToRemove = null; for (K cacheKey : cache.keys()) { if (keyComparator.compare(key, cacheKey) == 0) { keyToRemove = cacheKey; break; } } if (keyToRemove != null) { cache.remove(keyToRemove); } } return cache.put(key, value); } @Override public V get(K key) { return cache.get(key); } @Override public void remove(K key) { cache.remove(key); } @Override public void clear() { cache.clear(); } @Override public Collection<K> keys() { return cache.keys(); } } LimitedAgeMemoryCache implements MemoryCacheAware 在前面介绍过的MemoryCacheAware接口实现类中,有时可能需要添加这样一个额外的功能:当缓存的对象存在超过一定时间时,将其清理掉,LimitedAgeMemoryCache这个装饰者类就是实现这样一个功能。首先,实现一个缓存对象key到已存活时间的映射表,在获取缓存对象时,判断该对象是否超过最大存活时间,如果是则将其移除。代码如下所示: /** * Decorator for {@link MemoryCacheAware}. Provides special feature for cache: if some cached object age exceeds defined * value then this object will be removed from cache. * * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) * @see MemoryCacheAware * @since 1.3.1 */ public class LimitedAgeMemoryCache<K, V> implements MemoryCacheAware<K, V> { private final MemoryCacheAware<K, V> cache; private final long maxAge; private final Map<K, Long> loadingDates = Collections.synchronizedMap(new HashMap<K, Long>()); /** * @param cache Wrapped memory cache * @param maxAge Max object age <b>(in seconds)</b>. If object age will exceed this value then it'll be removed from * cache on next treatment (and therefore be reloaded). */ public LimitedAgeMemoryCache(MemoryCacheAware<K, V> cache, long maxAge) { this.cache = cache; this.maxAge = maxAge * 1000; // to milliseconds } @Override public boolean put(K key, V value) { boolean putSuccesfully = cache.put(key, value); if (putSuccesfully) { loadingDates.put(key, System.currentTimeMillis()); } return putSuccesfully; } @Override public V get(K key) { Long loadingDate = loadingDates.get(key); if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) { cache.remove(key); loadingDates.remove(key); } return cache.get(key); } @Override public void remove(K key) { cache.remove(key); loadingDates.remove(key); } @Override public Collection<K> keys() { return cache.keys(); } @Override public void clear() { cache.clear(); loadingDates.clear(); } } 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/4008097.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android -- Camera.ShutterCallback

干货 相机拍照的回调 /** * Equivalent to takePicture(shutter, raw, null, jpeg). * * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback) */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { takePicture(shutter, raw, null, jpeg); } 那么,让拍照的时候有“咔嚓”的声音,就需要去处理这个ShutterCallback Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() { @Override public void onShutter() { try { AudioManager meng = (AudioManager) TakePhotoActivity.this.getSystemService(Context.AUDIO_SERVICE); int volume = meng.getStreamVolume(AudioManager.STREAM_NOTIFICATION); if (volume != 0) { if (mShootSound == null) { mShootSound = MediaPlayer.create(TakePhotoActivity.this, Uri.parse("file:///system/media/audio/ui/camera_click.ogg")); } if (mShootSound != null) { mShootSound.start(); } } } catch (Exception e) { e.getStackTrace(); } } }; 我是天王盖地虎的分割线 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/4201967.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android -- Messenger与Service

如果你需要你的service和其他进程通信,那么你可以使用一个Messenger来提供这个接口。 这种方法允许你在不使用 AIDL的情况下,进行跨进程通信IPC。 实现步骤 下面是一个如何使用 Messenger的小总结: 1. service实现一个 Handler 接收客户端每一次调用的回调。 2. Handler 用来创建一个Messenger对象,它是一个Handler的引用。 3. Messenger创建一个 IBinder,service从 onBind()中把它返回给客户端。 4. 客户端使用这个IBinder来实例化Messenger (service的Handler的引用),客户端使用它来向service发送Message对象。 5. service在它的Handler中接收每一个Message对象,在它的 handleMessage()方法中。 Code public class MessengerService extends Service { /** Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mMessenger = new Messenger(new IncomingHandler()); /** * When binding to the service, we return an interface to our messenger for * sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT) .show(); return mMessenger.getBinder(); } } 注意 Handler中的 handleMessage() 方法是service接收到来的 Message并且决定做什么的地方。 客户端需要做的仅仅是创建一个基于service所返回的 IBinder的 Messenger,然后用 send()方法发送信息。 比如,这里有一个简单的activity和service绑定并且发送信息给service: public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean mBound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service); mBound = true; } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound = false; } }; public void sayHello(View v) { if (!mBound) return; // Create and send a message to the service, using a supported 'what' // value Message msg = Message .obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } } 注意这个例子并没有展示service如何响应客户端,如果你想要service响应,你需要在客户端中创建一个 Messenger。 然后当客户端接收到onServiceConnected()回调方法时,它会发送一个 Message到service,在它的send() 方法的replyTo参数中包含了客户端的Messenger。 我是天王盖地虎的分割线 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3950480.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android -- SharedPreferences存储信息

背景 SharedPreferences我觉得是最容易上手的,以xml方式存储。 代码 public class share { public static void saveInfo(Context context,String username,String password) { SharedPreferences sp = context.getSharedPreferences("config", context.MODE_PRIVATE); Editor editor = sp.edit(); editor.putString("username", username); editor.putString("password", password); editor.commit(); } } 主要就是开启edit,然后写数据,然后commit。 SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE); String username = sp.getString("username", ""); String password = sp.getString("password", ""); usernameText.setText(username); passwordText.setText(password); 上面的是读数据。 我是天王盖地虎的分割线 源代码:http://pan.baidu.com/s/1dD1Qx01 savefile_share.zip 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3720656.html,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册