屬性動畫與圖片三級緩存

屬性動畫

  1. 動畫: UI漸變, 變量值的變化
  2. ObjectAnimator : ofInt(“backgroundColor”,start,end);
  3. ValueAnimator:

    1. for(int i = start; i< end; i++) { a = i; }

      ValueAnimator animation=ValueAnimator.ofInt(start,end);
      animation.setDuration(DURATION);
      animation.addUpdateListener(new AnimatorUpdateListener() {
      
      @Override
      public void onAnimationUpdate(ValueAnimator animation)
      {
          int animationValue=(Integer) animation.getAnimatedValue();
          mHeaderlayout.setPadding(0, animationValue, 0, 0);
      }
      

      });
      animation.start();

刷新頁面是使用ValueAnimator場景之一,以提高用戶體驗性。addUpdateListener這個方法不斷更新高度,使其漸變收縮。從一開始的start到end。其他地方法就不介紹了,想了解的就去看看源碼吧。

ListView頁面數據點擊已讀的設置

實現條目點擊的事件,把點擊條目的唯一標識符id存儲起來,通知listview適配器更新。

    listviewAdapter.notifyDataSetChanged();

在listview適配器中的getView()方法中判斷當前position的id是否在存儲的數據中(自定義區分的規則),若存在,設置文本字體爲灰色,不存在則爲黑色。

    //設置已讀爲灰色
    String itemId="#"+bean.id+"#";
    String readIds=GetDataShared.getString(mContext, KEY_READ_LIST);
    boolean isRead=!TextUtils.isEmpty(readIds)&& readIds.contains(itemId);
    holder.textlist.setTextColor(isRead ? Color.GRAY:Color.BLACK);

頁面中webView的使用

    WebView listWeb=(WebView) findViewById(R.id.news_detial_wv);
    //根據url去加載數據
    listWeb.loadUrl(url);

    //設置webview參數
    WebSettings setting=listWeb.getSettings();//獲取webview的設置

    //默認爲false,不支持javascrip,設置爲true可收縮
    setting.setJavaScriptEnabled(true);//設置js可用

    setting.setBuiltInZoomControls(true); //設置放大和縮小可見

    setting.setUseWideViewPort(true);//設置手勢雙擊放大或縮小

改變webview中參數的大小:定義一個方法:mCurrentheckedItem爲存儲的值(0-4),要想做緩存就把mCurrentheckedItem的值存儲起來,在每次初始化的時候先判斷存儲的值是否存在且不爲空。

private void initTextSize()
{
    TextSize ts =null;
    switch(mCurrentheckedItem){
        case 0:
            ts=TextSize.LARGEST;
            break;
        case 1:
            ts=TextSize.LARGER;
            break;
        case 2:
            ts=TextSize.NORMAL;
            break;
        case 3:
            ts=TextSize.SMALLER;
            break;
        case 4:
            ts=TextSize.SMALLEST;
            break;
    }
    listWeb.getSettings().setTextSize(ts);
}

設置監聽常用的兩個API,第一個無法滿足需求就可以使用第二個。

    //設置監聽1,進度條的顯示切換在這裏監聽
    listWeb.setWebViewClient(new WebViewClient(){
        @Override
        public void onPageFinished(WebView view, String url)
        {
            //數據加載完成時調用,隱藏進度條
            listPb.setVisibility(View.GONE);
        }
    });

    //監聽2,進度條的更新要在這個api裏監聽
    listWeb.setWebChromeClient(new WebChromeClient(){
        @Override
        public void onProgressChanged(WebView view, int newProgress)
        {
            //更新進度條
            Log.i(TAG, newProgress+"");
        }
    });

自定義加載時環形進度條

把一個xml文件嵌套進進度條中:環形正向和反向同時轉然後匯聚再分開,循環

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <rotate
            android:fromDegrees="-90"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="990" >
            <shape
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:innerRadius="20dp"
                android:shape="ring"
                android:thickness="5dp"
                android:useLevel="false" >
                <gradient
                    android:endColor="#88ffffff"
                    android:startColor="#88ff0000"
                    android:type="sweep"
                    android:useLevel="false" />
            </shape>
        </rotate>
    </item>
    <item>
        <rotate
            android:fromDegrees="990"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="-90" >
            <shape
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:innerRadius="20dp"
                android:shape="ring"
                android:thickness="5dp"
                android:useLevel="false" >
                <gradient
                    android:endColor="#88ffffff"
                    android:startColor="#88ff0000"
                    android:type="sweep"
                    android:useLevel="false" />
            </shape>
        </rotate>
    </item>

</layer-list>

在Probress中設置應用:設置屬性indeterminateDrawable,在這裏引用佈局

    <ProgressBar 
        android:id="@+id/news_detial_pb"
        android:layout_gravity="center"
        android:indeterminateDrawable="@drawable/loadingpb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

一鍵分享,使用第三方分享SDK,現在有大量的平臺提供分享,這裏以Mob爲例說明一下使用的方法。

1、首先在mob官網註冊一個賬號。創建應用, 獲取ShareSDK的AppKey

2、 下載SDK,點擊下載之後如下圖所以,點擊下載SDK的下載頁,展開平臺可以選擇其他的第三方平臺;demo也是這裏下載;

3、 快速集成(具體參考mob官方Android集成文檔)、

(1)、使用快速工具進行集成

(2)、配置AndroidManifest.xml 添加權限、添加activity信息、替換mob後臺申請的Appkey與各個平臺申請的key

4、添加分享代碼

private void showShare() {
 ShareSDK.initSDK(this);
 OnekeyShare oks = new OnekeyShare();
 //關閉sso授權
 oks.disableSSOWhenAuthorize(); 

// 分享時Notification的圖標和文字  2.5.9以後的版本不調用此方法
 //oks.setNotification(R.drawable.ic_launcher, getString(R.string.app_name));
 // title標題,印象筆記、郵箱、信息、微信、人人網和QQ空間使用
 oks.setTitle(getString(R.string.share));
 // titleUrl是標題的網絡鏈接,僅在人人網和QQ空間使用
 oks.setTitleUrl("http://sharesdk.cn");
 // text是分享文本,所有平臺都需要這個字段
 oks.setText("我是分享文本");
 // imagePath是圖片的本地路徑,Linked-In以外的平臺都支持此參數
 //oks.setImagePath("/sdcard/test.jpg");//確保SDcard下面存在此張圖片
 // url僅在微信(包括好友和朋友圈)中使用
 oks.setUrl("http://sharesdk.cn");
 // comment是我對這條分享的評論,僅在人人網和QQ空間使用
 oks.setComment("我是測試評論文本");
 // site是分享此內容的網站名稱,僅在QQ空間使用
 oks.setSite(getString(R.string.app_name));
 // siteUrl是分享此內容的網站地址,僅在QQ空間使用
 oks.setSiteUrl("http://sharesdk.cn");

// 啓動分享GUI
 oks.show(this);
 }

這裏就可以使用分享東西到多社交平臺了。

ShareSDK集成的主要步驟

  1. 註冊賬號
  2. 創建應用
  3. 下載sdk
  4. SDK 導入配置
  5. 代碼配置

圖片的三級緩存## 圖片的三級緩存

  1. 引用

    1. 強引用: 應用程序崩潰時都不會回收,成員變量
    2. 軟引用: 當應用程序內存不足的時候,系統會回收(JVM) SoftReference
    3. 弱引用:當jvm的回收機制運行時,就回收
    4. 虛引用:應用場景很少
  2. 3.0: bitmap緩存時,用軟引用

  3. LruCache: Lru less recently use

首先是頁面要顯示圖片,到內存中取圖片數據,發現內存中沒有,之後到本地中查詢,有數據就存到內存中,頁面從內存中取出數據顯示;若本地也沒有數據,就到網絡取數據,取出數據就存到本地中,再存到內存中,最後顯示出來。這就是三級緩存的大概步驟。下面來看看圖片流程:

下面就來看看代碼如何實現這些步驟

package com.cca.zhihui.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

/**
 * 
 * @包名:com.cca.zhihui.utils
 * @類名:CacheHelper
 * @時間:下午11:07:15
 * @author Administrator
 * 
 * @描述:三級緩存的實現原理
 */
public class ImageHelper
{
    public static LruCache<String, Bitmap>  mCaches = null;
    // private Map<String ,SoftReference<Bitmap>>

    private static String                           mCacheDir; //系統緩存目錄

    private static Handler mHandler;            //handler機制

    private ExecutorService mPool;      //線程管理者
    private static Map<ImageView,Future<?>> mFuture;
    public ImageHelper(Context context) {
        if (mCaches == null)
        {
            // lru最大佔用的應用的內存
            int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);
            mCaches = new LruCache<String, Bitmap>(maxSize) {
                @Override
                protected int sizeOf(String key, Bitmap value)
                {
                    return value.getByteCount();
                    // 低版本:value.getRowBytes() * value.getHeight()
                }
            };

        }
        mCacheDir = getCacheDir(context);
        if(mHandler==null){
            mHandler=new ImagHandler();
        }
        //線程管理
        if(mPool==null){
            mPool=Executors.newFixedThreadPool(3);//只允許開3個子線程
        }
        if(mFuture==null){
            mFuture=new LinkedHashMap<ImageView, Future<?>>();//需要連續的內存地址
        }
    }

    //方法圖片顯示
    public void display(ImageView view, String url)
    {
        // 1、到內存中取數據
        Bitmap bitmap = mCaches.get(url);
        if (bitmap != null)
        {
            // 內存中有數據
            view.setImageBitmap(bitmap);
            return;
        }
        // 內存中沒有數據
        // 2、到本地中取數據
        bitmap = getBitmapFromLocal(url);
        if (bitmap != null)
        {
            // 本地中有數據
            view.setImageBitmap(bitmap);
            return;
        }
        // 本地也沒有數據
        getBitmapFromNet(view, url);
    }

    private void getBitmapFromNet(ImageView view, String url)
    {
        // 去網絡獲取數據
        //new Thread(new ImageRequestTask(view, url)).start();
        //判斷是否有已經在執行的
        Future<?> future=mFuture.get(view);
        if(future!=null && future.isDone() && !future.isCancelled()){
            //正在執行
            future.cancel(true);
            future=null;
        }
        future=mPool.submit(new ImageRequestTask(view, url));
        mFuture.put(view, future);
    }

    //從本地獲取圖片資源
    private Bitmap getBitmapFromLocal(String url)
    {
        // 首先找到文件
        String name;
        try
        {
            name = MD5Encoder.encode(url);
            File file = new File(mCacheDir, url);//mCacheDir、緩存目錄
            if (file.exists())
            {
                // 解析文件爲bitmap
                Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

                // 存到內存中
                mCaches.put(url, bitmap);
                return bitmap;
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    //獲取兩種存儲緩存的目錄
    private String getCacheDir(Context context)
    {
        // 如果有sdcard就用Android/data/appname
        if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState())
        {
            // 有sd卡
            File sdDir = Environment.getExternalStorageDirectory();
            File dir = new File(sdDir, "/Android/data/" + context.getPackageName() + "/bitmap/");
            if (!dir.exists())
            {
                dir.mkdirs();
            }
            return dir.getAbsolutePath();
        }
        else
        {
            return context.getCacheDir().getAbsolutePath();
        }

    }

    //異步加載圖片數據
    class ImageRequestTask implements Runnable
    {

        private String      url;
        private ImageView   view;

        public ImageRequestTask(ImageView iv, String url) {
            this.url = url;
            this.view = iv;
        }

        @Override
        public void run()
        {
            try
            {
                // 去網絡獲取數據
                HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
                conn.setConnectTimeout(5000);// 連接超時
                conn.setReadTimeout(5000);// 讀取超時
                conn.connect();// 開啓連接
                int code = conn.getResponseCode();
                if (code == 200)
                {
                    // 訪問網絡成功
                    // 獲取流,將流解析成bitmap
                    InputStream in = conn.getInputStream();
                    Bitmap bitmap = BitmapFactory.decodeStream(in);

                    // 存到本地
                    writeLocal(bitmap, url);
                    // 存到內存
                    mCaches.put(url, bitmap);

                    //主線程中刷新圖片
                    Message msg=Message.obtain();
                    msg.obj=new Object[]{view,url};
                    mHandler.sendMessage(msg);

                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    class ImagHandler extends Handler{
        @Override
        public void handleMessage(Message msg)
        {
            Object[] objs=(Object[]) msg.obj;
            ImageView view=(ImageView) objs[0];
            String url=(String) objs[1];
            //設置UI顯示
            display(view, url);
        }
    }

    //把圖片數據寫進本地
    public void writeLocal(Bitmap bitmap, String url)
    {
        String name;
        FileOutputStream fos=null;
        try
        {
            name = MD5Encoder.encode(url);
            File file = new File(mCacheDir, name);

            fos = new FileOutputStream(file);

            //壓縮圖片寫進本地,jpeg格式,質量爲100
            bitmap.compress(CompressFormat.JPEG, 100, fos);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (fos != null){
                try
                {
                    fos.close();
                    fos=null;
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}
發佈了40 篇原創文章 · 獲贊 9 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章