如何用Android studio开发一个实现基本功能的新闻app?——简闻(源码及教程)

一、系统需求分析

启动程序后,通过登陆注册进行程序,能够进行新闻资讯的实时更新,点击新闻可以查看新闻的详细内容,在详情页点击收藏,能够将新闻添加到收藏列表中,再次点击,取消收藏,并可以通过个人信息页面设置个人的信息。

功能需求:

(1) 登陆注册

(2) 获取和更新新闻

(3) 收藏新闻

(4) 修改个人信息

应用界面:

在这里插入图片描述
在这里插入图片描述

Github地址:https://github.com/LIANYCL/SimpleNews

CSDN下载地址:https://download.csdn.net/download/weixin_45636641/12654845

报告等资源文末关注公众号

在这里插入图片描述

二、系统总体设计

2.1 系统整体结构

在这里插入图片描述

源代码文件结构图:

在这里插入图片描述

2.2 数据存储设计

2.2.1用户信息E-R图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bd93EzNC-1595484734040)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1595483441520.png)]

2.2.2 新闻数据E-R图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J9DYUziX-1595484734043)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1595483503247.png)]

2.2.3 收藏数据E-R图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwGRYwL6-1595484734045)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1595483531078.png)]

三、系统详细设计

3.1 注册功能

用户输入用户名,邮箱和密码,遍历用户表,若是用户名已存在或邮箱已注册,提醒用户重新输入,否则注册成功,返回登陆页面

3.2 登陆功能

将用户输入的用户名和密码,与数据库存储的用户表对比,完全正确则进入新闻页面

3.3 查看新闻列表

页面初始化时,向服务器请求数据,对请求到的的json数据进行解析,并包装成List,最后展示在新闻列表页面

3.4 新闻详情页面

展示新闻详情,增加一个收藏按钮,实现收藏新闻和取消收藏的功能,同步更新数据库

3.5 个人信息页面

实现修改个人信息,包括性别、居住城市和个性签名

3.6 我的收藏页面

展示收藏的新闻,点击可以查看新闻详情,并取消收藏

四、系统实现

4.1 注册功能

通过LitePal操作数据库,遍历用户表,判断用户名和密码是否正确

users = DataSupport.findAll(User.class);
register.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View v) {
    
    
        for(User user: users){
    
    
            if (registerName.getText().toString().equals(user.getName())||
                    registerMail.getText().toString().equals(user.getMail())){
    
    
                flag = false;
                break;
            }
        }
        if (flag){
    
    
            User user = new User();
            //开始组装数据
            user.setName(registerName.getText().toString());
            user.setMail(registerMail.getText().toString());
            user.setPassword(registerPass.getText().toString());
            //保存数据
            user.save();
            Toast.makeText(Register.this, "注册成功", Toast.LENGTH_SHORT).show();
            finish();
        }else {
    
    
            Toast.makeText(Register.this, "用户名或邮箱已存在!", Toast.LENGTH_SHORT).show();
        }
    }
});

4.2 登陆功能

//用户名和密码
    name = (EditText) findViewById(R.id.login_name);
    pass = (EditText) findViewById(R.id.login_password);

    //登陆验证
    Button login = (Button) findViewById(R.id.login_button);
    login.setOnClickListener(new View.OnClickListener() {
    
    
        @Override
        public void onClick(View v) {
    
    
            List<User> users = DataSupport.select("name","password").find(User.class);
            if (!(TextUtils.isEmpty(name.getText().toString()))&&
                    !(TextUtils.isEmpty(pass.getText().toString()))){
    
    
                for (User user:users){
    
    
                    if (name.getText().toString().equals(user.getName())
                            && pass.getText().toString().equals(user.getPassword())){
    
    
                        Toast.makeText(MainActivity.this, "登陆成功", Toast.LENGTH_SHORT).show();
                        flag = false;
                        Intent intent = new Intent(MainActivity.this,Index.class);
                        intent.putExtra("username",name.getText().toString());
                        startActivity(intent);
                    }
                }
                if (flag){
    
    
                    Toast.makeText(MainActivity.this, "账户或密码错误!", Toast.LENGTH_SHORT).show();
                }
            }else {
    
    
                Toast.makeText(MainActivity.this, "账号密码不能为空", Toast.LENGTH_SHORT).show();
            }
        }
    });

    //注册跳转
    Button main_register = (Button) findViewById(R.id.main_register_button);
    main_register.setOnClickListener(new View.OnClickListener() {
    
    
        @Override
        public void onClick(View v) {
    
    
            Intent intent = new Intent(MainActivity.this,Register.class);
            startActivity(intent);
        }
    });
}

4.3 查看新闻列表

4.3.1新闻列表的获取
//新闻列表的获取
    lvNews = (ListView)findViewById(R.id.lvNews);
    dataList = new ArrayList<Data>();
    adapter = new NewsAdapter(this, dataList);
    lvNews.setAdapter(adapter);
    //点击列表项跳转页面
    lvNews.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
    
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    
    
            Data data = dataList.get(position);
            Intent intent = new Intent(Index.this, BrowseNewsActivity.class);
            intent.putExtra("title",data.getTitle());
            intent.putExtra("author_name",data.getAuthorName());
            intent.putExtra("date",data.getDate());
            intent.putExtra("pic_url",data.getThumbnail_pic_s());
            intent.putExtra("content_url", data.getUrl());
            startActivity(intent);
        }
    });
    sendRequestWithOKHttp();

    //下拉刷新
    swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
    swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
    swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    
    
        @Override
        public void onRefresh() {
    
    
            sendRequestWithOKHttp();
        }
    });
}

4.3.2数据的解析
private void sendRequestWithOKHttp(){
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("http://v.juhe.cn/toutiao/index?type=top&key=b646373d5b1b0d7628c7ae1bfae514d0")
                            .build();
                    Response response = null;
                    response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    Log.d("测试:", responseData);
                    parseJsonWithGson(responseData);
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
                //更新Adapter(务必在主线程中更新UI!!!)
                runOnUiThread(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        adapter.notifyDataSetChanged();
                        swipeRefresh.setRefreshing(false);
                    }
                });
            }
        }).start();
    }

    private void parseJsonWithGson(String jsonData){
    
    
        Gson gson = new Gson();
        News news = gson.fromJson(jsonData, News.class);
        List<Data> list = news.getResult().getData();
        for (int i=0; i<list.size(); i++){
    
    
            String uniquekey = list.get(i).getUniqueKey();
            String title = list.get(i).getTitle();
            String date = list.get(i).getDate();
            String category = list.get(i).getCategory();
            String author_name = list.get(i).getAuthorName();
            String content_url = list.get(i).getUrl();
            String pic_url = list.get(i).getThumbnail_pic_s();
            dataList.add(new Data(uniquekey, title, date, category, author_name, content_url, pic_url));
        }
    }

4.4 新闻详情页面

//接收传来的数据
title = getIntent().getStringExtra("title");
author_name = getIntent().getStringExtra("author_name");
date = getIntent().getStringExtra("date");
pic_url = getIntent().getStringExtra("pic_url");
content_url = getIntent().getStringExtra("content_url");
num = getIntent().getIntExtra("num",1);
//初始化布局
Toolbar toolbar = (Toolbar) findViewById(R.id.browse_toolbar);
setSupportActionBar(toolbar);
browseDL = (DrawerLayout) findViewById(R.id.browse_drawer);
ActionBar actionBar = getSupportActionBar();
if (actionBar!=null){
    
    
    actionBar.setDisplayHomeAsUpEnabled(true);
}
webView = (WebView)findViewById(R.id.webView);
webView.loadUrl(content_url);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

4.5 个人信息页面

4.5.1设置性别
//设置性别
info_gender.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View v) {
    
    
        new AlertDialog.Builder(Infomation.this).setTitle("请选择你的性别")
                .setItems(gender, new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
    
    
                        info_gender.setText(gender[which].toString());
                        User user_gender = new User();
                        user_gender.setGender(gender[which].toString());
                        user_gender.updateAll("name = ?",info_user);
                    }
                }).show();
    }
});

4.5.2设置城市
final String[] city = new String[]{
    
    
        "广州市","深圳市","清远市","韶关市","河源市","梅州市","潮州市","肇庆市",
        "云浮市","佛山市","东莞市","惠州市","汕尾市","揭阳市","汕头市","湛江市",
        "茂名市","阳江市","江门市","中山市","珠海市 "
};
//设置城市
info_location.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View v) {
    
    
        new AlertDialog.Builder(Infomation.this).setTitle("请选择你的城市")
                .setItems(city, new DialogInterface.OnClickListener() {
    
    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
    
    
                        info_location.setText(city[which].toString());
                        User user_location = new User();
                        user_location.setLocation(city[which].toString());
                        user_location.updateAll("name = ?",info_user);
                    }
                }).show();
    }
});

4.5.3编辑个性签名
final EditText motto = (EditText) findViewById(R.id.new_motto);
    motto.setText(getIntent().getStringExtra("motto"));
    final String alter_name = getIntent().getStringExtra("alter_name");
    //修改个性签名
    Button alter_motto = (Button) findViewById(R.id.alter_motto);
    alter_motto.setOnClickListener(new View.OnClickListener() {
    
    
        @Override
        public void onClick(View v) {
    
    
            User user_motto = new User();
            user_motto.setMotto(motto.getText().toString());
            user_motto.updateAll("name=?",alter_name);
            finish();
        }
    });
}

4.6 收藏功能

使用奇偶数实现对新闻是否被收藏的状态进行判断

FAB = (FloatingActionButton) findViewById(R.id.float_collection);
if (num%2==0){
    
    
    ColorStateList colorStateList = ContextCompat.getColorStateList(getApplicationContext(),R.color.colorPrimary);
    FAB.setBackgroundTintList(colorStateList);
}
//收藏
news = DataSupport.findAll(Colltects.class);
FAB.setOnClickListener(new View.OnClickListener() {
    
    
    @Override
    public void onClick(View v) {
    
    
        if (num%2==1){
    
    
            ColorStateList colorStateList = ContextCompat.getColorStateList(getApplicationContext(),R.color.colorPrimary);
            FAB.setBackgroundTintList(colorStateList);
            num++;
            for (Colltects conew:news){
    
    
                if (title.equals(conew.getTitle())&&author_name.equals(conew.getAuthor_name())){
    
    
                    flag = false;
                    Toast.makeText(BrowseNewsActivity.this, "已收藏", Toast.LENGTH_SHORT).show();
                }
            }
            if (flag){
    
    
                Colltects coll = new Colltects(title,author_name,date,content_url);
                coll.save();
                Toast.makeText(BrowseNewsActivity.this, "已收藏", Toast.LENGTH_SHORT).show();
            }

        }else {
    
    
            ColorStateList colorStateList = ContextCompat.getColorStateList(getApplicationContext(),R.color.colorAccent);
            FAB.setBackgroundTintList(colorStateList);
            num++;
            DataSupport.deleteAll(Colltects.class,"title = ? and author_name = ?",title,author_name);
            Toast.makeText(BrowseNewsActivity.this, "取消收藏", Toast.LENGTH_SHORT).show();
        }
    }
});

五、结论与心得体会

遇到的问题

  1. 编辑框的样式设计

通过网上搜索,才明白需要单独设置一个样式,再让编辑框或按钮使用这个样式,通过这样,可以便捷设置样式,减少代码的重复

  1. Json数据的解析

新闻数据的获取是通过聚合数据提供的,前期主要时间都花费在解析数据上,参考了几个案例,才明白的

  1. AlertDialog解决多页面

通过百度了解它的使用方法,使用它,实现对性别,城市等简单信息的设置,但是不知道如何使它拥有编辑框,最终只能采取,使用一个Activity来实现个性签名的设置

  1. 用户信息的同步

百度没找到方法,只能使用最笨的不断intent传递信息,效率低下,等后续学到了别的方法,再优化了

  1. 收藏按钮的颜色变化

网上的方法看不懂,最后通过奇偶数,对收藏状态进行简单判断,后设置按钮颜色,以及相应数据库的操作

心得体会:

遇到的问题

  1. 编辑框的样式设计

通过网上搜索,才明白需要单独设置一个样式,再让编辑框或按钮使用这个样式,通过这样,可以便捷设置样式,减少代码的重复

  1. Json数据的解析

新闻数据的获取是通过聚合数据提供的,前期主要时间都花费在解析数据上,参考了几个案例,才明白的

  1. AlertDialog解决多页面

通过百度了解它的使用方法,使用它,实现对性别,城市等简单信息的设置,但是不知道如何使它拥有编辑框,最终只能采取,使用一个Activity来实现个性签名的设置

  1. 用户信息的同步

百度没找到方法,只能使用最笨的不断intent传递信息,效率低下,等后续学到了别的方法,再优化了

  1. 收藏按钮的颜色变化

网上的方法看不懂,最后通过奇偶数,对收藏状态进行简单判断,后设置按钮颜色,以及相应数据库的操作

心得体会:

通过这次实验体会到一个功能完善的app需要注意的事情太多了,各种同步,数据库操作,直接的关系,同时也明白现在所学的知识不够的。目前自己仍然停留在学会如何使用已经有的方法,一旦找不到相对应的解决方法,自己就无从下手,只能采用最笨的方式,同时对系统的整体架构设计,已经各种类应该具备怎么样的设计,这些都是未来需要好好学习提高的。

关注微信公众号JavaStudys,获取更多干货
回复关键字“简闻”获取
注意:因为本人从事Java后端开发,该课程设计仅为完成作业,后续没有深入学习,仅能保证没有改动过源码,若出现bug等,请自行百度解决。
JavaStudys

猜你喜欢

转载自blog.csdn.net/weixin_45636641/article/details/107535558