2025年3月31日 星期一 乙巳(蛇)年 正月初一 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 安卓(android)开发

Android 新闻页demo之MVC模式

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

简单介绍一下新闻页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

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

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