Android期末项目 新闻APP的设计与实现
1 项目基本信息
1.1 项目名称
好好学习新闻APP的设计与实现
1.2 开发运行环境
Android Studio 2022
Android SDK 7.0
SQLite 5.4.1
Gradle 7.5
JDK 1.8.0
虚拟机 Pixel 2 API 30 2
1.3 使用的核心类及组件
Activity:Android系统中的四大组件之一,它是一种应用程序组件,用于提供用户交互界面和对用户输入的处理,每个Activity都会占用一个窗口来展示它的界面。
AppCompatActivity:支持Fragment的管理和兼容,在处理多个Fragment时,可以方便地使用FragmentTransaction等API进行管理和切换。
ViewPager:是Android中的一个控件,它是一个可以滑动切换子视图的容器,通常用于实现Tab切换、引导页面和轮播图等。
ListView:通过使用Adapter机制来绑定数据和视图,Adapter需要提供数据和视图,并根据数据创建对应的视图展示在ListView中。
Fragment:它可以让开发者在一个Activity中管理多个界面片段,使得界面的组合更加灵活。这些Fragment可以被添加到或移除出Activity中,而不影响其他Fragment以及整个Activity。
SQLiteOpenHelper:封装了SQLite数据库的一些底层操作,可以更加便捷地进行数据的存储和查询。同时,该类还提供了一些常用的API,如insert()、update()、delete()和query()等方法,分别用于执行插入、更新、删除和查询等数据操作。
2 项目需求分析
2.1 APP前台部分
(1)用户登录:如果用户想查看“好好学习新闻APP”的内容,首先必须使用账号和密码进行登录,也可点击记住密码,账号密码验证成功后可进入访问。
(2)用户注册:如果用户没有账号和密码,可以点击注册通过注册获取账号和密码,输入想要注册的账号和密码同意协议后点击注册可完成注册。
(3)用户浏览:用户通过账号密码登录成功后可以浏览新闻,用户可以选择推荐、要闻、思想、综合模块进行新闻浏览。
(4)用户查看:用户通过选择推荐、要闻、思想、综合这四个模块进行新闻查看,若遇到感兴趣的标题可以点进去查看全文。
3 项目开发过程
3.1 APP功能模块
3.1.1 用户登录功能:用户通过账号密码登录成功后可以进入系统内访问或者阅读当前新闻内容。
3.1.2 用户注册功能:如果用户没有访问该系统的权限,可以通过注册功能注册用户账号密码,注册成功后跳转登陆页面。
3.1.3页面浏览功能:用户注册并登录成功后,可以进入系统浏览推荐、要闻、思想、综合这四个新闻页面。
3.1.4 新闻查看功能:如果用户发现非常感兴趣的新闻标题或图片,可以点击该新闻进入详情页面进行阅读。
APP功能模块图
3.2 数据库设计
本APP在设计数据库时需要使用User表来实现。
用户表
字段 | 数据类型 | 主键 | 外键 | 是否为空 | 说明 |
Uid | char(32) | 是 | 否 | 否 | 用户Id |
Account | varchar(50) | 否 | 否 | 否 | 用户账号 |
Pass | varchar(50) | 否 | 否 | 否 | 用户密码 |
用户表实体图
3.3具体实现
3.1.1 用户登录功能:用户通过账号密码登录成功后可以进入系统内访问或者阅读当前新闻内容,如果用户经常忘记密码也可以点击记住密码选项。用户若没有账号密码可以点击右下角“还没有账号”跳转注册页面进行注册。
部分代码:
public class LoginActivity extends AppCompatActivity { private Button btnLogin; private EditText etAccount, etPassword; private TextView toReg; private CheckBox cb_Remember; private MySQLiteOpenHelper mySQLiteOpenHelper; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); initView(); initData(); //设置点击监听按钮 btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String account = etAccount.getText().toString(); String password = etPassword.getText().toString(); List userList = mySQLiteOpenHelper.selectByAccountAndPass(account,password); System.out.println(userList); if(!userList.isEmpty()){ //说明查到了 Toast.makeText(LoginActivity.this,"登录成功!",Toast.LENGTH_LONG).show(); if(cb_Remember.isChecked()){ SharedPreferences spf = getSharedPreferences("spfRecorid",MODE_PRIVATE); SharedPreferences.Editor edit = spf.edit(); edit.putString("account", account); edit.putString("password",password); edit.putBoolean("isRemember",true); edit.apply(); }else{ SharedPreferences spf = getSharedPreferences("spfRecorid",MODE_PRIVATE); SharedPreferences.Editor edit = spf.edit(); edit.putBoolean("isRemember",false); edit.apply(); } Intent intent = new Intent(LoginActivity.this,FragmentMain.class); startActivity(intent); }else{ Toast.makeText(LoginActivity.this,"账号或密码错误!",Toast.LENGTH_LONG).show(); } } }); toReg = findViewById(R.id.toReg); toReg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(LoginActivity.this,RegisterActivity.class); startActivity(intent); } }); } private void initView(){ btnLogin = findViewById(R.id.btn_login); etAccount = findViewById(R.id.et_account); etPassword = findViewById(R.id.et_password); mySQLiteOpenHelper = new MySQLiteOpenHelper(this); cb_Remember = findViewById(R.id.cb_Remember); } // 记住密码初始化功能 private void initData(){ SharedPreferences spf = getSharedPreferences("spfRecorid",MODE_PRIVATE); boolean isRem = spf.getBoolean("isRemember",false); String account = spf.getString("account",""); String password = spf.getString("password",""); if(isRem){ etAccount.setText(account); etPassword.setText(password); cb_Remember.setChecked(true); } } }
3.1.2 用户注册功能:如果用户没有访问该系统的权限,可以通过注册功能注册用户账号密码,用户通过输入需要注册的账号密码并点击同意协议便可完成注册,注册成功后跳转登陆页面。若用户有账号和密码可以点击“已有账号”跳转登录页面进行登录。
部分代码:
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener{ private EditText etAccount, etPass, etPassConfirm; private Button btnRegister, button2; private CheckBox cbAgree; private MySQLiteOpenHelper mySQLiteOpenHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); // 返回登录页面 button2 = (Button) findViewById(R.id.button2); etAccount = findViewById(R.id.et_account1); etPass = findViewById(R.id.et_password1); etPassConfirm = findViewById(R.id.et_password_confirm); btnRegister = findViewById(R.id.btn_register); cbAgree = findViewById(R.id.cb_Agree); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Intent intent = new Intent(MainActivity.this,DetailActivity.class); Intent intent = new Intent(RegisterActivity.this,LoginActivity.class); startActivity(intent); } }); // 第二种方式写监听事件 btnRegister.setOnClickListener(this); } @Override public void onClick(View view) { String account = etAccount.getText().toString().trim(); String pass = etPass.getText().toString().trim(); String passConfirm = etPassConfirm.getText().toString(); // TextUtils.isEmpty() 和 name.isEmpty() 的区别 // 第一个可以判断 NULL 和 “” 两种为空的情况,且均判断为空 // 第二个只能判断“”这一种情况,如果为NULL则会报空指针异常。 if(TextUtils.isEmpty(account)){ Toast.makeText(RegisterActivity.this,"用户名不能为空", Toast.LENGTH_LONG).show(); return; } mySQLiteOpenHelper = new MySQLiteOpenHelper(this); // 查询这个账号是否已经被注册 List userList = mySQLiteOpenHelper.selectByAccount(account); if(!userList.isEmpty()){ //说明已经被注册过了 Toast.makeText(RegisterActivity.this,"该账号已经被注册!",Toast.LENGTH_LONG).show(); return; } if(TextUtils.isEmpty(pass)){ Toast.makeText(RegisterActivity.this,"密码不能为空",Toast.LENGTH_LONG).show(); return; } if(!TextUtils.equals(pass,passConfirm)){ Toast.makeText(RegisterActivity.this,"两次密码不一致",Toast.LENGTH_LONG).show(); return; } if(!cbAgree.isChecked()){ Toast.makeText(RegisterActivity.this,"请同意用户协议",Toast.LENGTH_LONG).show(); return; } User user = new User(); user.setAccount(account); user.setPass(pass); //插入数据到数据库中 mySQLiteOpenHelper = new MySQLiteOpenHelper(this); long rowId = mySQLiteOpenHelper.insertData(user); if(rowId != -1){ ToastUtil.toastShort(this,"注册成功"); Intent intent = new Intent(RegisterActivity.this,LoginActivity.class); startActivity(intent); }else { ToastUtil.toastShort(this,"注册失败"); } } }
3.1.3 页面浏览功能:用户注册并登录成功后,可以进入系统浏览推荐、要闻、思想、综合这四个新闻页面。用户可以根据个人兴趣进行选择。
部分代码:
public class FragmentMain extends AppCompatActivity { ViewPager viewPager; List viewList; TextView tuijian, yaowen, sixiang, zonghe; List titlelist; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragmentmian); viewPager = findViewById(R.id.viewpager); tuijian = findViewById(R.id.tuijian); yaowen = findViewById(R.id.yaowen); sixiang = findViewById(R.id.sixiang); zonghe = findViewById(R.id.zonghe); MyLister lister = new MyLister(); tuijian.setOnClickListener(lister); yaowen.setOnClickListener(lister); sixiang.setOnClickListener(lister); zonghe.setOnClickListener(lister); viewList = new ArrayList(); // View view1 = View.inflate(this, R.layout.fragment01, null); // View view2 = View.inflate(this, R.layout.fragment02, null); // View view3 = View.inflate(this, R.layout.fragment03, null); // View view4 = View.inflate(this, R.layout.fragment04, null); titlelist=new ArrayList(); titlelist.add("推荐"); titlelist.add("要闻"); titlelist.add("思想"); titlelist.add("综合"); // viewList.add(view1); // viewList.add(view2); // viewList.add(view3); // viewList.add(view4); viewList.add(new Fragment01()); viewList.add(new Fragment02()); viewList.add(new Fragment03()); viewList.add(new Fragment04()); //FragPageAdapter pageAdapter = new FragPageAdapter(viewList,titlelist); FragmentManager manager=getSupportFragmentManager(); viewPager.setAdapter(new FragfragAdapter(manager,viewList,titlelist)); class MyLister implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { case R.id.tuijian: viewPager.setCurrentItem(0); break; case R.id.yaowen: viewPager.setCurrentItem(1); break; case R.id.sixiang: viewPager.setCurrentItem(2); break; case R.id.zonghe: viewPager.setCurrentItem(3); break; } } } }
3.1.4 新闻查看功能:用户登录成功后通过浏览推荐、要闻、思想、综合这四个新闻页面,如果发现非常感兴趣的新闻标题或图片,可以点击该新闻进入详情页面进行阅读。
部分代码:
public class Fragment01 extends Fragment { private ListView Lv = null; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { //解析碎片对应的布局文件 View view= inflater.inflate(R.layout.fragment01,container,false); // return view; Lv = view.findViewById(R.id.Lv); final String[] name = new String[] { "******" }; final String[] message = new String[] { "******", "******", "******", "******", "******"}; final int[] photo = new int[] { R.drawable.tuijian02, R.drawable.tuijian03, R.drawable.yaowen01 ,R.drawable.sixiang01, R.drawable.zonghe01}; List data = new ArrayList(); Map map1 = new HashMap(); map1.put("photo", R.drawable.tuijian02); map1.put("name", name[0]); data.add(map1); Map map2 = new HashMap(); map2.put("photo", R.drawable.tuijian03); map2.put("name", name[1]); data.add(map2); Map map3 = new HashMap(); map3.put("photo", R.drawable.yaowen01); map3.put("name", name[2]); data.add(map3); Map map4 = new HashMap(); map4.put("photo", R.drawable.sixiang01); map4.put("name", name[3]); data.add(map4); Map map5 = new HashMap(); map5.put("photo", R.drawable.zonghe01); map5.put("name", name[4]); data.add(map5); System.out.println(data); Lv.setAdapter(new SimpleAdapter(getActivity(), data, R.layout.item, new String[] { "photo", "name" }, new int[] { R.id.iv,R.id.tv_name })); Lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView arg0, View arg1, int arg2,long arg3) { Bundle bundle = new Bundle(); bundle.putInt("photo", photo[arg2]); bundle.putString("message", message[arg2]); Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(getActivity(), NewsTuijian.class); Log.i("message", message[arg2]); getActivity().startActivity(intent); // startActivity(intent); } }); return view; } }
4 项目总结及心得
通过这次学习,我了解到Activity作为Android开发系统中的四大组件之一,它的功能非常强大,用于提供用户交互界面和对用户输入的处理,每个Activity都会占用一个窗口来展示它的界面。以及AppCompatActivity支持Fragment的管理和兼容,在处理多个Fragment时,可以方便地使用进行管理和切换,使得界面的组合更加灵活。
个人设计是最容易提升自身代码水平的,通过这次设计,我深刻的认识到学习新技术和工具是必须的,Android生态系统每年都在迅速发展和壮大,新技术和工具不断涌现,作为学生我们需要保持持续学习,跟上技术发展的步伐。另外好的代码设计和架构对于项目成功至关重要:良好的代码设计和架构可以提高代码质量,同时还有助于提高应用的性能和稳定性。
注:由于源码量过多,需要的朋友可在资源中下载,也可私信我拿取!