文件下载

文件下载:

实现文件下载管理,实现单线程断点续传,界面显示多个下载记录,

但只能点击单独一个可以继续下载,如果点击多个出现相应提示,在下载

列表里将所有Sdcard下的PDF文件全部显示出来,点击调用PDF浏览器,

如果没有浏览器提示无法显示。

完成已经下载完成的文件查看,删除:

MVC

V层Adapter实现

C层Activity实现

V和C层实现 订购/通知

M层使用单例,工厂,模板

 

C层中将需求提出:

1,  查询目录下的文件返回List

2,  删除指定文件(参数文件名)

3,  查看指定文件(参数文件名,context上下文)

由DownloadedInterface接口声明以上的3个方法,

由于1,2需求是不会改变的,但是在3中如果文件是PDF,DOC,TXT那么在打开的时候具体的逻辑是不同的。

那么就可以用模板方式将前2个需求实现,将第三个需求定义成抽象,子类继承模板类单独实现抽象的3需求,好处是如果需求更改,需要加入其他文件类型的时候只需要继承模板类实现需求3就可以了,因为需求1,2是不变的。

 

如果需求更改,需要在Activity中添加多个DownloadedInterface的获取指定文件的类,或者添加多个判断:

判断是pdf,判断是doc,判断是txt。

这样C层中的代码复用可能性也不大,有没有什么好的方式去解耦呢?

可以使用工厂模式,

DownloadedObjectFactory类(单例),私有构造中声明List里面加上map,key是文件类型(其实就相当于文件夹的路径),value是Obj的(需要将符合Key的类装入到list中进行缓存,这样的好处是在初始化的时候耗时,但是以后就不需要再创建,并且是全局的随时可以使用)。在构造中添加所有的文件类比如doc,txt,pdf等等,DownloadedObjectFactory定义成单例,在下面有getDownloadObjForName方法(参数是文件名/文件夹名)返回DownloadedInterface这样在使用的时候只需要将文件名或文件夹名传入,返回的自然就是你需要的类了,如果需要扩展只需要,继承模板类实现需求3,并在list中加入key和value,在使用的时候直接

DownloadedInterface downloadedInterface =DownloadedObjectFactory.getInstance().getDownloadObjForName(文件名/文件夹名);就可以了

其实简单看好像没有什么必要实现工厂,但是这样可以实现解耦,并且C层是不需要知道用户需要的格式是什么格式,这样也保证了复用性。

以上是M层。

下面是C和V层之间的订购/通知实现,

interface DownloadedDelegat声明方法DownloadedDelegate(文件名,点击类型)

在V层定义DownloadedDelegat,并实现set方法,在长按(暂定删除)调用DownloadedDelegate(文件名,长按类型),在点击查看时调用方法传入文件名和点击类型。

在c层Activity中实现DownloadedDelegat接口中的方法,adapter调用set代理,就可以实现订购/通知,而在实现的接口方法中可以判断点击的类型,并调用相应的删除/查看方法通知到M层去实现,C层必须知道V层传入的事件类型,但是没有必要知道具体操作的是什么文件,所以只要调用删除和查看,但是具体删除什么文件,查看什么文件C层是不需要知道的,这是需要M层做的事情。

不需要担心文件的类型出错只要传入的没有错,调用的就没有错,当创建的时候就是传入文件的类型,所以返回的接口肯定也是这个类型的。并且使用了单例和缓存中的list不会出现问题。

整个工程结构:

把源码传上来以备以后查阅(按包名类名):

package com.hsm.Activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity
{
  private Button b1;
  private Button b2;
  private Button b3;
  private Intent intent;
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.first);
    b1 = (Button)findViewById(R.id.button1);
    b2 = (Button)findViewById(R.id.button2);
    b3 = (Button)findViewById(R.id.button3);
    intent = new Intent();
    b1.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v)
      {
        // TODO Auto-generated method stub
        intent.setClass(MainActivity.this,ResumeBrokenDownloadsActivity.class);
        intent.putExtra("url", "http://192.168.10.113:8080/a.pdf");
        startActivity(intent);
      }
    });
    b2.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v)
      {
        // TODO Auto-generated method stub
        intent.setClass(MainActivity.this,ResumeBrokenDownloadsActivity.class);
        intent.putExtra("url", "http://192.168.10.113:8080/b.pdf");
        startActivity(intent);
      }
    });
    b3.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v)
      {
        // TODO Auto-generated method stub
        intent.setClass(MainActivity.this,ResumeBrokenDownloadsActivity.class);
        intent.putExtra("url", "http://192.168.10.113:8080/c.pdf");
        startActivity(intent);
      }
    });
  }
}

上面的是进入的首界面activity

下面是进入后显示已经下载完成的list的activity

package com.hsm.Activity;

import java.util.List;

import com.hsm.downloadedfile.DownloadedPDF;
import com.hsm.factory.DownloadedObjectFactory;
import com.hsm.modelinterface.DownloadedDelegat;
import com.hsm.modelinterface.DownloadedInterface;
import com.hsm.view.DownloadedAdapter;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ListView;

public class ResumeBrokenDownloadsActivity extends Activity implements DownloadedDelegat{
    /** Called when the activity is first created. */
    private List<String> list ;
    private ListView downloadedListView;
    private DownloadedAdapter downloadedAdapter;
    private DownloadedInterface downloadedInterface;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //显示已经下载完成的文件
        downloadedInterface = DownloadedObjectFactory.getInstance().getDownloadObjForName("pdf");
        list = downloadedInterface.queryDownloadedFiles();
        downloadedAdapter = new DownloadedAdapter(this, list);
        downloadedAdapter.setDelegate(this);
        downloadedListView = (ListView)findViewById(R.id.downloaded_list);
        downloadedListView.setAdapter(downloadedAdapter);
        //显示正在下载的文件
        Intent intent = getIntent();
        String nameString = intent.getStringExtra("url");
        //TODO 如果nameString是空就表示从其他入口进来不是从下载入口进来
        
        
    }
    @Override
    public void DownloadedDelegate(String name, int event)
    {
      if (event==1)//删除
      {
        downloadedInterface.removeFileForName(name);
        Message msg = new Message();
        msg.obj = "flush";
        flushHandler.sendMessage(msg);
      }else if(event==2){//查看
        downloadedInterface.openDownloadedFile(name,this);
      }
    }
    //刷新已下载完成的Adapter
    private Handler flushHandler = new Handler() {
      public void handleMessage(Message msg)
      {
        if ("flush".equals(msg.obj))
        {
          downloadedAdapter.notifyDataSetChanged();
        }
      }
    };
}

 下面是具体实现查询下载完成Fild逻辑的类:

package com.hsm.downloadedfile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.widget.Toast;

import com.hsm.modelinterface.DownloadedInterface;

public abstract class DownloadedFild implements DownloadedInterface
{
  protected List<String> pdfList;
  protected File sdDir;
  protected String sdPath = Environment.getExternalStorageDirectory().toString();// 获取跟目录
  public DownloadedFild(String folderPath) {
    String status = Environment.getExternalStorageState();
    if (status.equals(Environment.MEDIA_MOUNTED))
    {
      pdfList = new ArrayList<String>();
      sdDir = new File(sdPath+"/"+folderPath);
      File[] allFile = sdDir.listFiles();
      for (int i = 0; i < allFile.length; i++)
      {
        pdfList.add(allFile[i].getName());
      }
    }else {
      //TODO 否则表示无sdcard
    }
  }
  @Override
  public List<String> queryDownloadedFiles()
  {
    return pdfList;
  }

  @Override
  public void removeFileForName(String fileName)
  {
    pdfList.remove(fileName);
    File file = new File(sdDir+"/"+fileName);
    if (!file.exists())
    {
      return;
    }
    // 如果file的路径是文件夹
    // if (!file.isDirectory())
    // {
    // return;
    // }
    file.delete();
  }

  @Override
  public abstract void openDownloadedFile(String fileName , Context context);
}

 下面的是实现删除具体文件的类继承了上面的查询类DownloadedFild只实现了public abstract void openDownloadedFile(String fileName , Context context);

package com.hsm.downloadedfile;

import java.io.File;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.Toast;

public class DownloadedPDF extends DownloadedFild
{
  public DownloadedPDF(String folderPath)
  {
    super(folderPath);
  }

  @Override
  public void openDownloadedFile(String fileName, Context context)
  {
    Intent intent = new Intent("android.intent.action.VIEW");
    intent.addCategory("android.intent.category.DEFAULT");
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    Uri localUri = Uri.fromFile(new File(sdDir+"/"+fileName));
    intent.setDataAndType(localUri, "application/pdf");
    try
    {
      context.startActivity(intent);
    }
    catch (Exception e)
    {
      // TODO Auto-generated catch block
      Toast.makeText(context, "无可用程序打开此文件!", 0).show();
    }
  }

}

 

posted @ 2012-01-09 11:23  飞翔的熊猫  阅读(371)  评论(0编辑  收藏  举报