照片墙的实现,是需要往手机里面添加很多图片的,如果没有对资源进行合理的释放,程序很快就会出现OOM.所以需要用到LruCache算法来缓存图片.


1,首先是图片资源类,这个类中包含了很多图片链接.
public class AllImages {
    public final static String[] imageUrls = new String[] {
            "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
            "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg",
            "http://img.my.csdn.net/uploads/201308/31/1377949442_4562.jpg" };
}
2.有了图片,还需要一个图片的工具类.新建一个ImageTools.
//图片处理的工具类
public class ImageTools {
    //图片缓存,用于缓存所有下载好的图片
    private static LruCache<String, Bitmap> mMemoryCache;
    
    //ImageTools实例
    private static ImageTools imageTools;
    
    public ImageTools() {
        //获取应用程序的最大可用内存
        int maxMemory=(int)Runtime.getRuntime().maxMemory();
        int cacheMemory=maxMemory/8;
        mMemoryCache=new LruCache<String, Bitmap>(cacheMemory){
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount();
            }
        };
    }
    //获取ImageTools的实例
    public static ImageTools getInstance(){
        if(imageTools==null){
            imageTools=new ImageTools();
        }
        return imageTools;
    }
    //将图片放入LruCache中
    public void addBitmapToMemoryCache(String key,Bitmap bitmap){
        if(getBitmapFromMemoryCache(key)==null){
            mMemoryCache.put(key, bitmap);
        }
    }
    //从LruCache中获取一张图片,如果不存在就返回null
    public Bitmap getBitmapFromMemoryCache(String key){
        return mMemoryCache.get(key);
    }
    //求出图片需要压缩的比例
    public static int calculateInSampleSize(BitmapFactory.Options option,int reqWidth){
        //得到原图片的宽度
        final int width=option.outWidth;
        int inSampleSize=1;
        if(width>reqWidth){
            //计算出实际宽度与目标宽度的比例
            final int widthRadio=Math.round((float)width/(float)reqWidth);
            inSampleSize=widthRadio;
        }
        return inSampleSize;
    }
    //压缩图片
    public static Bitmap decodeSampedBitmapFromResource(String pathName,int reqWidth){
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
        final BitmapFactory.Options options=new Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(pathName, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(pathName, options);
    }
}
这里将ImageTools设为单例,并在构造函数中初始化了LruCache类,提供了操作LruCache的读取和增加方法  以及两个对图片进行处理的方法.
3.接下来就是最重要的MyScrollView类.核心类.
public class MyScrollView extends ScrollView  implements OnTouchListener {
    //每页要加载的图片数量
    public static final int PAGE_SIZE=15;
    //记录当前加载到了第几页
    private int page;
    //每一列的宽度
    private int columnWidth;
    //第一列的高度
    private int firstColumnHeight;
    //第二列的高度
    private int secondColumnHeight;
    //第三列的高度
    private int thirdColumnHeight;
    //是否已经加载过Layout
    private boolean loadOnce;
    //对图片进行管理的工具类
    private ImageTools imageTools;
    //第一列的布局
    private LinearLayout firstColumn;
    //第二列布局
    private LinearLayout secondColumn;
    //第三列布局
    private LinearLayout thirdColumn;
    //MyScrollView下的子布局
    private static View scrollLayout;
    //MyScrollView的高度
    private static int scrollViewHeight;
    //记录上次垂直滚动的距离
    private static int lastScrollY=-1;
    //记录界面上所有的图片
    private List<ImageView> imageList=new ArrayList<ImageView>();
    
    //记录所有正在下载的任务
    private static Set<LoadImageTask> imageTaskList;
    
    private static Handler mh=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            MyScrollView mScrollView=(MyScrollView) msg.obj;
            int scrollY=mScrollView.getScrollY();
            if(scrollY==lastScrollY){  //如果当前滚动位置与上次滚动位置相同,则说明滚动停止
                // 当滚动的最底部,并且当前没有正在下载的任务时,开始加载下一页的图片
                if(scrollViewHeight+scrollY>=scrollLayout.getHeight()&&imageTaskList.isEmpty()){
                    mScrollView.loadMoreImage();
                }
                mScrollView.checkVisiblility();
            }
            else{
                lastScrollY=scrollY;
                Message message = new Message();
                message.obj = mScrollView;
                // 5毫秒后再次对滚动位置进行判断
                mh.sendMessageDelayed(message, 5);
            }
        }
    };
    
    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        imageTools=ImageTools.getInstance();
        imageTaskList=new HashSet<MyScrollView.LoadImageTask>();
        setOnTouchListener(this);
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction()==MotionEvent.ACTION_UP){
            Message msg=new Message();
            msg.obj=this;
            mh.sendMessageDelayed(msg,5);
        }
        return false;
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed&&!loadOnce){
            scrollViewHeight=getHeight();
            scrollLayout=getChildAt(0);
            firstColumn=(LinearLayout) findViewById(R.id.first_column);
            secondColumn=(LinearLayout) findViewById(R.id.second_column);
            thirdColumn=(LinearLayout) findViewById(R.id.third_column);
            columnWidth=firstColumn.getWidth();
            loadOnce=true;
            loadMoreImage();
        }
    }
    
    //加载更多图片
    public void loadMoreImage(){
        if(hasSDCard()){
            int startIndex=PAGE_SIZE*page;
            int endIndex=PAGE_SIZE*page+PAGE_SIZE;
            if(startIndex<AllImages.imageUrls.length){  //判断图片是否已经加载完毕
                Toast.makeText(getContext(), "正在加载",Toast.LENGTH_SHORT).show();
                if(endIndex>AllImages.imageUrls.length){
                    endIndex=AllImages.imageUrls.length;
                }
                for (int i = startIndex; i < endIndex; i++) {
                    LoadImageTask task=new LoadImageTask();
                    imageTaskList.add(task);
                    task.execute(AllImages.imageUrls[i]);
                }
                page++;
            }
            else{
                Toast.makeText(getContext(), "加载完毕",Toast.LENGTH_SHORT).show();
            }
        }
        else{
            Toast.makeText(getContext(), "没有内存卡",Toast.LENGTH_SHORT).show();
        }
    }
    
    //对图片的可见性进行检查,如果已经移出视线外,则将图片设为一张空白图片
    public void checkVisiblility(){
        for (int i = 0; i < imageList.size(); i++) {
            ImageView imageView=imageList.get(i);
            int border_top=(Integer) imageView.getTag(R.string.border_top);
            int border_bottom=(Integer) imageView.getTag(R.string.border_bottom);
            if(border_bottom>getScrollY()&&border_top<getScrollY()+scrollViewHeight){   //检查是不是在可见视图之内
                String imageUrl=(String) imageView.getTag(R.string.image_url);
                Bitmap imageBitmap=imageTools.getBitmapFromMemoryCache(imageUrl);
                if(imageBitmap==null){
                    LoadImageTask task=new LoadImageTask(imageView);
                    task.execute(imageUrl);
                }
                else{
                    imageView.setImageBitmap(imageBitmap);
                }
            }
            else{  //如果已经不再屏幕内
                imageView.setImageResource(R.drawable.ic_launcher);
            }
        }
    }
    
    //判断手机是否有SD卡
    private boolean hasSDCard(){
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }
    
    //异步加载图片的任务
    class LoadImageTask extends AsyncTask<String, Void, Bitmap>{
        //图片地址Url
        private String imageUrl;
        //可重复使用的ImageView
        private ImageView mImageView;
        
        public LoadImageTask() {
            
        }
        //将可重复使用的ImageView传入
        public LoadImageTask(ImageView imageView) {
            this.mImageView=imageView;
        }
        
        @Override
        protected Bitmap doInBackground(String... params) { //根据imageUrl作为key值查找Bitmap,如果没有,调用loadImage去加载
            imageUrl=params[0];
            Bitmap imageBitmap=imageTools.getBitmapFromMemoryCache(imageUrl);
            if(imageBitmap==null){
                imageBitmap=loadImage(imageUrl);
            }
            return imageBitmap;
        }
        @Override
        protected void onPostExecute(Bitmap imageBitmap) {
            if(imageBitmap!=null){
                double ratio=imageBitmap.getWidth()/(columnWidth*1.0);   //得到宽度的压缩比
                int scaleHeight=(int)(imageBitmap.getHeight()/ratio);    //根据宽度的压缩比  得到这张图片的高度
                addImage(imageBitmap, columnWidth, scaleHeight);
            }
            imageTaskList.remove(this);
        }
        
        //根据图片的Url去加载图片   首先判断该图片是否在内存卡里面,如果没有,则去下载,如果有,则经过压缩处理后返回
        private Bitmap loadImage(String imageUrl){
            File imageFile=new File(getImagePath(imageUrl));
            if(!imageFile.exists()){
                downloadImage(imageUrl);
            }
            if(imageUrl!=null){
                Bitmap bitmap=ImageTools.decodeSampedBitmapFromResource(imageFile.getPath(), columnWidth);
                if(bitmap!=null){
                    imageTools.addBitmapToMemoryCache(imageUrl, bitmap);
                    return bitmap;
                }
            }
            return null;
        }
        
        
        //向ImageView中添加一张图片
        private void addImage(Bitmap bitmap,int imageWidth,int imageHeight){
            LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(imageWidth, imageHeight);
            if(mImageView!=null){
                mImageView.setImageBitmap(bitmap);
            }
            else{
                ImageView imageView=new ImageView(getContext());
                imageView.setLayoutParams(params);
                imageView.setImageBitmap(bitmap);
                imageView.setScaleType(ScaleType.FIT_XY);
                imageView.setPadding(5, 5, 5, 5);
                imageView.setTag(R.string.image_url,imageUrl);
                findColumnToAdd(imageView, imageHeight).addView(imageView);
                imageList.add(imageView);
                }
        }
        
        
        //找到应该添加图片的一列,选取三列中高度最小的一列返回.
        private LinearLayout findColumnToAdd(ImageView imageView,int imageHeight){
            if(firstColumnHeight<=secondColumnHeight){
                if(firstColumnHeight<=thirdColumnHeight){
                    imageView.setTag(R.string.border_top,firstColumnHeight);
                    firstColumnHeight+=imageHeight;
                    imageView.setTag(R.string.border_bottom,firstColumnHeight);
                    return firstColumn;
                }
                else{
                    imageView.setTag(R.string.border_top,thirdColumnHeight);
                    thirdColumnHeight+=imageHeight;
                    imageView.setTag(R.string.border_bottom,thirdColumnHeight);
                    return thirdColumn;
                }
            }
            else{
                if(secondColumnHeight<=thirdColumnHeight){
                    imageView.setTag(R.string.border_top,secondColumnHeight);
                    secondColumnHeight+=imageHeight;
                    imageView.setTag(R.string.border_bottom, secondColumnHeight);
                    return secondColumn;
                }
                else{
                    imageView.setTag(R.string.border_top,thirdColumnHeight);
                    thirdColumnHeight+=imageHeight;
                    imageView.setTag(R.string.border_bottom,thirdColumnHeight);
                    return thirdColumn;
                }
            }
        }
        
        //将图片下载到SD卡缓存
        private void downloadImage(String imageUrl){
            HttpURLConnection con=null;
            FileOutputStream fos=null;
            BufferedOutputStream bos=null;
            BufferedInputStream bis=null;
            File imageFile=null;
            try {
                URL url=new URL(imageUrl);
                con=(HttpURLConnection) url.openConnection();
                con.setConnectTimeout(5*1000);
                con.setReadTimeout(15*1000);
                con.setDoInput(true);
                con.setDoOutput(true);
                bis=new BufferedInputStream(con.getInputStream());
                imageFile =new File(getImagePath(imageUrl));//获得了图片的路径
                fos=new FileOutputStream(imageFile);
                bos=new BufferedOutputStream(fos);
                byte[] b=new byte[1024];
                int length;
                while((length=bis.read(b))!=-1){
                    bos.write(b, 0, length);
                    bos.flush();
                }
                
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            finally{
                    try {
                        if(bis!=null){
                            bis.close();
                        }
                        if(bos!=null){
                            bos.close();
                        }
                        if(con!=null){
                            con.disconnect();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
            if(imageFile!=null){
                //裁剪图片
                Log.e("info", "path---"+imageFile.getPath());
                Bitmap bitmap=ImageTools.decodeSampedBitmapFromResource(imageFile.getPath(), columnWidth);
                if(bitmap!=null){
                    imageTools.addBitmapToMemoryCache(imageUrl, bitmap);
                }
            }
        }
        
    }
    //获取图片的本地缓存路径
    private String getImagePath(String imageUrl){
        int lastIndex=imageUrl.lastIndexOf("/");
        String imageName=imageUrl.substring(lastIndex+1);
        String imageDir=Environment.getExternalStorageDirectory().getPath()+"/PhotoWallFall/";
        File file=new File(imageDir);
        if(!file.exists()){
            file.mkdirs();
        }
        String imagePath=imageDir+imageName;
        return imagePath;
    }

}  

这个自定义控件是继承自ScrollView类的,这样就允许用户可以通过滚动的方式浏览更多的图片,loadMoreImage()是专门用来浏览下一页图片的.


看一看loadMoreImages()方法的内部细节了。在这个方法中,使用了一个循环来加载这一页中的每一张图片,每次都会开启一
个LoadImageTask,用于对图片进行异步加载。然后在LoadImageTask中,首先会先检查一下这张图片是不是已经存在于SD卡中了,如果还没
存在,就从网络上下载,然后把这张图片存放在LruCache中。接着将这张图按照一定的比例进行压缩,并找出当前高度最小的一列,把压缩
后的图片添加进去就可以了。
另外,为了保证照片墙上的图片都能够合适地被回收,这里还加入了一个可见性检查的方法,即checkVisibility()方法。这个方法的核心思
想就是检查目前照片墙上的所有图片,判断出哪些是可见的,哪些是不可见。然后将那些不可见的图片都替换成一张空图,这样就可以保证
程序始终不会占用过高的内存。当这些图片又重新变为可见的时候,只需要再从LruCache中将这些图片重新取出即可。如果某张图片已经从
LruCache中被移除了,就会开启一个LoadImageTask,将这张图片重新加载到内存中.

4.打开activity_main.xml
<com.example.photodemo.MyScrollView 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:id="@+id/scroll_view"
    tools:context=".MainActivity" >
    
    <LinearLayout 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
        <LinearLayout 
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/first_column"
            android:orientation="vertical"
            ></LinearLayout>
                <LinearLayout 
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/second_column"
            android:orientation="vertical"
            ></LinearLayout>
                        <LinearLayout 
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/third_column"
            android:orientation="vertical"
            ></LinearLayout>
        
    </LinearLayout>
</com.example.photodemo.MyScrollView>

5.当然,因为是获取网络图片,所以必须加上联网权限 ,以及将图片缓存到SD卡,所以需要写权限.
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.INTERNET" />

 


android瀑布流照片墙实现代码详解的更多相关文章

  1. Android瀑布流照片墙实现,体验不规则排列的美感

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10470797 传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在 ...

  2. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  3. [JS练习] 瀑布流照片墙

    记录JS实现瀑布流照片墙效果 首先是前端页面 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  4. Android EventBus 3.0 实例使用详解

    EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥和启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解 ...

  5. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  6. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  7. Android瀑布流照片

    http://blog.csdn.net/guolin_blog/article/details/10470797 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候 ...

  8. Android 多线程之IntentService 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  9. Android 多线程之HandlerThread 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

随机推荐

  1. 根据值设置select的选中项

    $('.selector').attr("checked", true); <s:iterator value="jobSelect" id=" ...

  2. 泛型&&枚举

    1.枚举类型 JDk1.5中新增了枚举类型,可以使用该功能取代以往定义常量的方式,同时枚举类型还赋予程序在编译时进行检查的功能. 1.1 使用枚举类型设置常量 以往设置常量,通常将常量放在接口中(fi ...

  3. jQuery 效果使用

    .hide() 隐藏匹配的元素. .hide() 这个方法不接受任何参数. .hide([duration][,complete]) duration 一个字符串或者数字决定动画将运行多久. comp ...

  4. Make a Person-freecodecamp算法题目

    Make a Person 1.要求 用下面给定的方法构造一个对象:方法有 getFirstName(), getLastName(), getFullName(), setFirstName(fir ...

  5. centos下LVM配置与管理

    centos下LVM配置与管理 LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层, ...

  6. SVN中Commit出现乱码的解决方案【转载】

    http://blog.csdn.net/thinkingcao/article/details/52797737 这几天在电脑上装了一个SVN,把Eclipse里面的工程全部Delete掉了,然后在 ...

  7. Windows手工创建服务方法

    需要将程序设置成Windows服务的情况,可以利用一下windows自带的sc命令来创建服务. 该命令的基本用法如下:打开cmd命令, 输入如下信息:1 创建服务:sc create SecServe ...

  8. [Bzoj2246]迷宫探险(概率+DP)

    Description 题目链接 Solution 用三进制表示陷阱状态,1表示有害,2表示无害,0表示不知道 用\(f[S][i]\)表示状态为S时陷阱i有害的概率,这个可以预处理出 \(d[S][ ...

  9. 使用 Ajax

    Ajax( Asynchronous JavaScript and XML) 在 Ajax 中 Asynchronous 是指异步, 代表 客户端(Client 通常是指浏览器) 可以向服务器(Ser ...

  10. Struts2---环境搭建及包介绍

    导入jar包 jar包下载地址:http://www.apache.org/官网中选择struts,然后点击download下载.将jar包导入到WEB-INF下的lib文件目录下. asm-5.2. ...