您当前的位置:首页 > 计算机 > 编程开发 > 安卓(android)开发

Android 新闻页demo之MVC模式

时间:01-14来源:作者:点击数:

简单介绍一下新闻页demo

其中三个按钮包含三个逻辑

1.网络连线:这里采用的是HttpUrlConnection
2.获取资源文件:建立了assets文件夹,并把xml放在里面
3.数据库sqlite:因为前两个按钮都是在最后保存到了数据库,这里直接在数据库捞就好啦

当然也包含几个小知识点:

  • 自定义适配器(adapter)和holder结合
  • 自定义带缓存效果的ImageView
  • SharedPreferences保存用户行为
  • xml解析
  • 多线程并发,页面跳转传值,枚举使用以及接口定义等
在这里插入图片描述
在这里插入图片描述
下面附上主要代码:

MainActivity:MVC中的view部分

主要逻辑是根据枚举类型调用NewsManager(操作Controller)返回list,通过handler传给主线程(ui线程)并用listview显示出来

public class MainActivity extends AppCompatActivity {

    private ListView lv_newsList;
    private NewsManager newsManager;
    private Handler handler=new Handler(){
        @Override
        public void handleMessage( Message msg) {
            newsList = (List<NewsInfo>) msg.obj;
            lv_newsList.setAdapter(new NewsAdapter(newsList,MainActivity.this));


        }
    };
    private SharedPreferences sp;
    private List<NewsInfo> newsList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        String type = sp.getString("type",SourceType.SOURCE_FROM_SERVER.getType());
        String path = sp.getString("path", AppProperties.SERVER_PATH);
         showNewsList(path,SourceType.valueOf(type));
        intent();

    }

    private void intent() {
        lv_newsList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent();
                NewsInfo newsInfo =newsList.get(position);
                intent.putExtra(AppProperties.NEWS_INTENT_NAME,newsInfo);
                intent.setClass(MainActivity.this, ResultActivity.class);
                startActivity(intent);
            }
        });
    }

    private void initData() {
        sp = getSharedPreferences("news", MODE_PRIVATE);
        newsManager = new NewsManager();
    }

    private void initView() {
        lv_newsList = (ListView) findViewById(R.id.lv_newsList);
    }

    public void click(View view) {
        SharedPreferences.Editor edit = this.sp.edit();
        switch (view.getId()){
            case R.id.btn_server:
                edit.putString("type",SourceType.SOURCE_FROM_SERVER.getType());
                edit.putString("path",AppProperties.SERVER_PATH);
                showNewsList(AppProperties.SERVER_PATH,SourceType.SOURCE_FROM_SERVER);
                break;
            case R.id.btn_asset:
                edit.putString("type",SourceType.SOURCE_FROM_ASSETSS.getType());
                edit.putString("path",AppProperties.ASSETS_FILE_PATH);
                showNewsList(AppProperties.ASSETS_FILE_PATH,SourceType.SOURCE_FROM_ASSETSS);
                break;
                case R.id.btn_db:
                    edit.putString("type",SourceType.SOURCE_FROM_DB.getType());
                    edit.putString("path","");
                    showNewsList(null,SourceType.SOURCE_FROM_DB);
                break;
        }
        edit.commit();
    }

    private void showNewsList(final String path, final SourceType sourceType) {

        new Thread(){
            @Override
            public void run() {
                List<NewsInfo> newsList = newsManager.getNewsListFromSource(MainActivity.this,sourceType,path);
                Message msg = Message.obtain();
                msg.obj = newsList;
                handler.sendMessage(msg);
            }
        }.start();
    }
}

NewsManager:通过manager管理项目的逻辑部分

根据枚举判断按钮的点击,前两个按钮都有一个共同的功能点,就是获得输入流,一个是从网络端一个是从资源文件,这里定义了一个接口iSource

(Controller这一层是view和model的桥梁, 同时也管理应用逻辑)

public class NewsManager {

    public List<NewsInfo>getNewsListFromSource(Context context, SourceType sourceType,  String path){

        List<NewsInfo>newsList = null;
        switch (sourceType){
            case SOURCE_FROM_SERVER:
            case SOURCE_FROM_ASSETSS:
                newsList = getNewsListFromInputStream(context, sourceType, path);
                break;
            case SOURCE_INTENT:
                break;
            case SOURCE_FROM_DB:
                newsList = new NewsSqlOP(context).queryNewsList();
                break;
              default:
                  newsList = new ArrayList<>();
                  break;
        }
        return newsList;
    }

    private List<NewsInfo> getNewsListFromInputStream(Context context,SourceType sourceType, String path) {
        List<NewsInfo>newsList= new ArrayList<>();
        InputStream in=null;
        try {
            ISource iSource = SourceFactory.sourceCreate(context, sourceType);
            in=iSource.getInputStream(path);
            newsList = NewsXmlParser.parse(in);
            saveNewsInfo2DB(context,newsList);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ErrorResponseCodeException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return newsList;
    }
    private void saveNewsInfo2DB(final Context context, final List<NewsInfo>newsList) {

        new Thread(){
            @Override
            public void run() {
                NewsSqlOP newsSqlOP = new NewsSqlOP(context);
                int counter= 0;
                while (!newsSqlOP.insertWithException(newsList)){
                    System.out.println("--------failed");
                    if (counter++ == 3)
                        break;
                }
                if (counter!=4)
                    System.out.println("success");
            }
        }.start();
    }
}
ISource:
public interface ISource {
     InputStream getInputStream(String path) throws IOException, ErrorResponseCodeException;
}
SourceMap :这里使用hashmap的方式代替了switch case 减少了代码量
public class SourceMap {
    private static HashMap<SourceType,ISource>sourceMap;
    public  static HashMap<SourceType,ISource> getrateSource(Context context){
        if (sourceMap ==null){
            sourceMap = new HashMap<>();
            sourceMap.put(SourceType.SOURCE_FROM_SERVER,new HttpStreamOP());
            sourceMap.put(SourceType.SOURCE_FROM_ASSETSS,new AssetssStreamOP(context));
        }
        return sourceMap;
    }
}
经典的HttpURLConnection网络连线部分和获取assets文件
public class HttpStreamOP implements ISource {
    @Override
    public InputStream getInputStream(String path) throws IOException, ErrorResponseCodeException {
        InputStream in = null;
        URL url = new URL(path);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        int code = connection.getResponseCode();
        if (code == 200) {
             in = connection.getInputStream();
        } else {
            throw  new ErrorResponseCodeException("error request code is"+ code);
        }
        return  in;
    }
}
public class AssetssStreamOP implements ISource {

    private  Context context;
    public  AssetssStreamOP(Context context){
        this.context=context;
    }
    @Override
    public InputStream getInputStream(String path) throws IOException {

        return this.context.getAssets().open(path);

    }
}
自定义图片缓存类

采用了base64加密和bitmap的压缩

base64应用原因

1.转换成的字符串没有特殊字符

2.加密好的也是唯一的,不能重复

3.加密后的固定长度

public class ImageCache {

    private  Context context;
    public  ImageCache(Context context){

     this.context=context;
    }

    public Bitmap getBitmapFromUrl(String path){
        File file = new File(this.context.getCacheDir(), Base64.encodeToString(path.getBytes(),Base64.DEFAULT));
        if (file.exists() && file.length() >0){
        }else {
            try {
                InputStream inputStream = new HttpStreamOP().getInputStream(path);
               if (inputStream != null){
                   Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                   writeImage2Cache(bitmap,file);
                   return bitmap;
               }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ErrorResponseCodeException e) {
                e.printStackTrace();
                return  BitmapFactory.decodeResource(this.context.getResources(), R.mipmap.load_failure);
            }
        }
        return BitmapFactory.decodeFile(file.getAbsolutePath());
    }

    private void writeImage2Cache(final Bitmap bitmap, final File file) {

        if(bitmap == null || file == null)
            return;
        new Thread(){
            @Override
            public void run() {
                BufferedOutputStream bufferedOutputStream = null;
                FileOutputStream fileOutputStream =  null;
                try {
                    fileOutputStream= new FileOutputStream(file);
                    bufferedOutputStream = new BufferedOutputStream(fileOutputStream,2*1024);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, bufferedOutputStream);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }finally {
                        try {
                            bufferedOutputStream.flush();
                            bufferedOutputStream.close();
                            fileOutputStream.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
        }.start();
    }
}

滴滴,以上就是项目的主要部分,包含了许多的基础小知识点

github链接:https://github.com/871924230jp/Mytest

只是记录学习过程 若有错误 欢迎大佬指出

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门