Android基础整合项目(一) 之节日群发助手part 1

——转载请注明出处:coder-pig

本节引言:

Android入门系列已经写了大半了,学习了这么多理论知识,不练下手怎么行呢?

在实际的开发中我们会遇到更多的问题,同时也能加固我们的基础知识!鉴于

笔者的水平有限,该项目,面对的是初学者,各位大牛路过不喜勿喷!好吧说下第一个

练手项目吧,前几天中秋节今天又是教师节,各种祝福短信满天飞,手打再群发,条条

短信一个样,没意思!直接用别人弄好的短信群发,别人又不知道你是谁,起码加个:

亲爱的XXX.我是隔壁老王,.....别人起码知道你是谁把!好了,废话不多说,开始app

的开发吧!

ps:目前app的基本功能已经实现,效果图如下,如果有需要可以进行下载

到后面会逐步完善相关功能:

效果图:

参考代码下载:

源码下载

正文:

本节要点图:

开发流程详解:

1)创建数据库

创建数据库文件:有两个表,分别为存储联系人的表contacts和存储节日祝福语的表festival

可以直接使用SQLite Expert或者其他SQLite的可视化工具创建表,可以代码创建或者手动创建

代码创建的话执行以下语句生成数据库表:

"CREATE TABLE festival(sentence_id INTEGER PRIMARY KEY AUTOINCREMENT,detail)"

"CREATE TABLE contacts(_id INTEGER PRIMARY KEY,pname,pnumber,pstate)"

接着对节日表进行数据的录入,结束的表结构如下:

festival表:

contacts表:

2)应用启动时判断数据库文件是否存在

在完成上述创建数据库的步骤后,接着我们需要把数据库文件复制到assert目录

这里我们要做什么呢?

在应用启动的时候我们需要判断data/data/<包名>/database下有没有我们的数据库文件

如果不存在的话,我们需要通过代码将数据库文件导入到指定目录下!


①先定义我们的数据库名称以及包名常量:

[java] view plaincopyprint?
public static String dbName="my.db";//数据库的名字
private static String DATABASE_PATH="/data/data/com.jay.example.festivalsmshelper/databases/";

②接着定义判断是数据库文件是否存在的方法:

[java] view plaincopyprint?
  1. public boolean checkDataBase(){
  2. SQLiteDatabase checkDB = null;
  3. try{
  4. String databaseFilename = DATABASE_PATH+dbName;
  5. checkDB =SQLiteDatabase.openDatabase(databaseFilename, null,
  6. SQLiteDatabase.OPEN_READONLY);
  7. }catch(SQLiteException e){
  8. }
  9. if(checkDB!=null){
  10. checkDB.close();
  11. }
  12. return checkDB !=null?true:false;
  13. }

③假如数据库文件不存在的话我们需要将数据库文件复制到指定目录下:

[java] view plaincopyprint?
  1. public void copyDataBase() throws IOException{
  2. String databaseFilenames =DATABASE_PATH+dbName;
  3. File dir = new File(DATABASE_PATH);
  4. if(!dir.exists())//判断文件夹是否存在,不存在就新建一个
  5. dir.mkdir();
  6. FileOutputStream os = null;
  7. try{
  8. os = new FileOutputStream(databaseFilenames);//得到数据库文件的写入流
  9. }catch(FileNotFoundException e){
  10. e.printStackTrace();
  11. }
  12. InputStream is = MainActivity.this.getAssets().open("my.db");
  13. byte[] buffer = new byte[4096];
  14. int count = 0;
  15. try{
  16. while((count=is.read(buffer))>0){
  17. os.write(buffer, 0, count);
  18. os.flush();
  19. }
  20. }catch(IOException e){e.printStackTrace();}
  21. is.close();
  22. os.close();
  23. }
    public void copyDataBase() throws IOException{
String databaseFilenames =DATABASE_PATH+dbName;
File dir = new File(DATABASE_PATH);
if(!dir.exists())//判断文件夹是否存在,不存在就新建一个
dir.mkdir();
FileOutputStream os = null;
try{
os = new FileOutputStream(databaseFilenames);//得到数据库文件的写入流
}catch(FileNotFoundException e){
e.printStackTrace();
}
InputStream is = MainActivity.this.getAssets().open("my.db");
byte[] buffer = new byte[4096];
int count = 0;
try{
while((count=is.read(buffer))>0){
os.write(buffer, 0, count);
os.flush();
}
}catch(IOException e){e.printStackTrace();}
is.close();
os.close();
}

④在MainActivity的onCreate()方法中加入下面的代码,用于调用上述两个方法:

[java] view plaincopyprint?
  1. boolean dbExist = checkDataBase();
  2. if(dbExist){}
  3. else{//不存在就把assert里的数据库写入手机
  4. try{
  5. copyDataBase();
  6. }catch(IOException e){throw new Error("复制数据库出错");}
  7. }
 boolean dbExist = checkDataBase();
if(dbExist){}
else{//不存在就把assert里的数据库写入手机
try{
copyDataBase();
}catch(IOException e){throw new Error("复制数据库出错");}
}

⑤打开File Exploer查看数据库文件是否复制完毕:


如图就说明数据库文件复制完毕,是仅仅有一个my.db文件而已!后面那个my.do-journal是因为执行了

其他的操作生成的!

3)读取系统的联系人目录:

这里的话我们读取的仅仅是联系人的目录,并不包括sim卡中的联系人哦!

这块就涉及到了我们前面所学的使用系统提供的ContentProvider了!

我们先把系统提供的联系人的数据库文件找出来瞅瞅吧!

打开文件浏览器:data/data/com.android.providers.contacts/databases

下面的contacts2.db文件就是存储系统联系人的数据库文件了:

导出以后查看几个重要的基本表,以及相关字段:

contacts表

data表

phone_look_up表

raw_contact表

以上四个就是我们要留意的四个表了

好了,说下我们要获取的数据:联系人id,姓名,一个电话号码

于是我们定义一个类GetPhone类并定义一个读取联系人的方法,将读到数据存储到list集合中:

代码如下:

[java] view plaincopyprint?
  1. public static List<Person> getPerson(Context context)
  2. {
  3. List<Person> persons = new ArrayList<Person>();
  4. ContentResolver cr = context.getContentResolver();
  5. Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
  6. while(cursor.moveToNext()){
  7. Person person = new Person();
  8. //获取联系人id
  9. String contatId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
  10. person.setId(Integer.parseInt(contatId));
  11. //获取联系人姓名
  12. String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
  13. person.setName(name);
  14. //因为一个联系人的电话号码可能有几个,但我们这里仅仅是获取一个就够了,所以就不循环遍历了
  15. Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
  16. null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+contatId, null, null);
  17. phones.moveToFirst();
  18. String num = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
  19. person.setNumber(num);
  20. person.setState(-1);
  21. persons.add(person);
  22. phones.close();
  23. }
  24. cursor.close();
  25. return persons;
  26. }
public static List<Person> getPerson(Context context)
{
List<Person> persons = new ArrayList<Person>();
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
while(cursor.moveToNext()){
Person person = new Person();
//获取联系人id
String contatId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
person.setId(Integer.parseInt(contatId));
//获取联系人姓名
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
person.setName(name);
//因为一个联系人的电话号码可能有几个,但我们这里仅仅是获取一个就够了,所以就不循环遍历了
Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+contatId, null, null);
phones.moveToFirst();
String num = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
person.setNumber(num);
person.setState(-1);
persons.add(person);
phones.close();
}
cursor.close();
return persons;
}

4)定义一个插入数据的方法:

该方法的参数是一个Person的对象,我们使用ContentValues来存储从person取出的不同数据!

再调用db.insert("contacts",null,contentValue)将记录插入到contacts表中

代码:

[java] view plaincopyprint?
  1. public void insert(Person person){
  2. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  3. ContentValues values = new ContentValues();
  4. values.put("_id", person.getId());
  5. values.put("pname", person.getName());
  6. values.put("pnumber", person.getNumber());
  7. values.put("pstate", person.getState());
  8. db.insert("contacts", null, values);
  9. }
 public void insert(Person person){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("_id", person.getId());
values.put("pname", person.getName());
values.put("pnumber", person.getNumber());
values.put("pstate", person.getState());
db.insert("contacts", null, values);
}

5)在MainActivity中调用获取联系人的方法,插入数据

怕数据太多,出现卡住的情况,加个进度条,用户看着没那么不爽!

再new一个线程,一秒钟后让进度条消失,第一个界面消失,通过intent跳转

到第二个界面中!

代码:

[java] view plaincopyprint?
  1. //加个进度条,数据太多可能卡住不好,用户看着不爽
  2. final ProgressDialog dialog = ProgressDialog.show(this, "提示", "读取联系人中", false, true);
  3. GetContactsService getContacts = new GetContactsService(getApplicationContext());
  4. List<Person> persons = GetPerson.getPerson(MainActivity.this);
  5. Cursor cursor = getContacts.query("select count(*) from contacts", null);
  6. cursor.moveToFirst();
  7. //判断联系人数目是否发生变更,没变更的话就不用调用下面的for循环了
  8. if(persons.size() != cursor.getInt(0))
  9. {
  10. for(Person p : persons)
  11. {
  12. System.out.println(p.toString());
  13. getContacts.insert(p);
  14. }
  15. }
  16. //设置让圆形进度条过一秒后消失,以及第一个界面消失,跳转到第二个界面
  17. new Thread()
  18. {
  19. public void run()
  20. {
  21. try {
  22. sleep(1000);
  23. } catch (InterruptedException e) {e.printStackTrace();}
  24. dialog.dismiss();
  25. Intent it = new Intent(getApplicationContext(), ChooseActivity.class);
  26. startActivity(it);
  27. finish();
  28. };
  29. }.start();
     //加个进度条,数据太多可能卡住不好,用户看着不爽
final ProgressDialog dialog = ProgressDialog.show(this, "提示", "读取联系人中", false, true);
GetContactsService getContacts = new GetContactsService(getApplicationContext());
List<Person> persons = GetPerson.getPerson(MainActivity.this);
Cursor cursor = getContacts.query("select count(*) from contacts", null);
cursor.moveToFirst();
//判断联系人数目是否发生变更,没变更的话就不用调用下面的for循环了
if(persons.size() != cursor.getInt(0))
{
for(Person p : persons)
{
System.out.println(p.toString());
getContacts.insert(p);
}
}
//设置让圆形进度条过一秒后消失,以及第一个界面消失,跳转到第二个界面
new Thread()
{
public void run()
{
try {
sleep(1000);
} catch (InterruptedException e) {e.printStackTrace();}
dialog.dismiss();
Intent it = new Intent(getApplicationContext(), ChooseActivity.class);
startActivity(it);
finish();
};
}.start();

6)运行后的效果查看:

将my.db文件导出后可以看到contacts表的data已经有数据了,就完成了

另外记得还有个Person类别漏了,定义四个属性:id,name,number,state(记录是否已经发送)

这里就不给出了,另外要创建出第二个Activity完成Intent的跳转哦!不然可是会报错的!

知识点总结:

1.判断app中的数据库文件是否存在?不存在的话如何使用输入流将文件写入到相应目录下

2.如何获得assert里的文件,从而获得输入流对象;

3.哪里可以找到系统保存联系人的数据库;相关表以及字段的了解!

读取表中我们需要的联系人信息!

4.调用database的insert()方法插入ContentValues类型的数据

5.获得数据库表有多少条记录的方法:

Cursor cursor = getContacts.query("select count(*) from contacts", null);

cursor.moveToFirst();

cursor.getInt(0);

6.获取List集合中的数据元素:list.size();

好了这一节就暂且到这里吧,如果对本文有什么建议,批评的,欢迎指出!

不慎感激!项目的代码会随着后面深入慢慢完善的!

Android基础整合项目(一) 之节日群发助手part 2

——转载请注明出处:coder-pig

本节引言:

在上一节中我们已经做出了我们群发助手的第一个界面以及完成了联系人的读取以及数据库的

录入了,在这一节中将要完成的工作是:

1)自定义我们的ListView的列表项,两个TextView + CheckBox;

2)使用SimpleCursorAdapter将数据显示到ListView上;

3)实现listview的全选与全不选

4)点击重置按钮后,将数据库中的state都重置为-1

好了,那么开始本节的内容吧!

正文:

1.创建第二个Activity的布局:

布局代码如下:

[html] view plaincopyprint?
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/RelativeLayout1"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. tools:context="com.jay.example.festivalsmshelper.MainActivity" >
  8. <TextView
  9. android:id="@+id/TextView1"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:layout_alignParentLeft="true"
  13. android:layout_alignParentTop="true"
  14. android:text="选择要发送的人" />
  15. <ListView
  16. android:id="@+id/listcontacts"
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent"
  19. android:layout_alignParentLeft="true"
  20. android:layout_below="@+id/TextView1"
  21. android:layout_above="@+id/buttomlayout"
  22. android:layout_marginTop="10dp" >
  23. </ListView>
  24. <LinearLayout
  25. android:id="@+id/buttomlayout"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:layout_alignParentBottom="true"
  29. android:layout_alignParentLeft="true"
  30. android:orientation="horizontal" >
  31. <Button
  32. android:layout_width="wrap_content"
  33. android:layout_height="wrap_content"
  34. android:id="@+id/btnall"
  35. android:text="全选" />
  36. <Button
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:id="@+id/btnreset"
  40. android:text="重置" />
  41. <Button
  42. android:id="@+id/btnnext"
  43. android:layout_width="wrap_content"
  44. android:layout_height="wrap_content"
  45. android:text="下一步" />
  46. <TextView
  47. android:layout_marginLeft="20dp"
  48. android:layout_width="wrap_content"
  49. android:layout_height="wrap_content"
  50. android:text="已选"
  51. android:textSize="15sp" />
  52. <TextView
  53. android:layout_marginLeft="20dp"
  54. android:layout_width="wrap_content"
  55. android:layout_height="wrap_content"
  56. android:id="@+id/textshow"
  57. android:textSize="15sp" />
  58. </LinearLayout>
  59. </RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.jay.example.festivalsmshelper.MainActivity" >
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="选择要发送的人" />
<ListView
android:id="@+id/listcontacts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="@+id/TextView1"
android:layout_above="@+id/buttomlayout"
android:layout_marginTop="10dp" >
</ListView>
<LinearLayout
android:id="@+id/buttomlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnall"
android:text="全选" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnreset"
android:text="重置" />
<Button
android:id="@+id/btnnext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一步" />
<TextView
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已选"
android:textSize="15sp" />
<TextView
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textshow"
android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>

2.创建Listview的列表项布局文件:

其实就是三等分了布局,另外还隐藏了两个textview

代码如下:

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="horizontal"
  6. android:gravity="center_horizontal"
  7. >
  8. <TextView
  9. android:gravity="center"
  10. android:id="@+id/listid"
  11. android:layout_width="0dp"
  12. android:layout_weight="1"
  13. android:layout_height="match_parent"
  14. android:visibility="gone"
  15. />
  16. <TextView
  17. android:gravity="center"
  18. android:id="@+id/listname"
  19. android:layout_width="0dp"
  20. android:layout_weight="1"
  21. android:layout_height="match_parent"
  22. />
  23. <TextView
  24. android:gravity="center"
  25. android:id="@+id/listphone"
  26. android:layout_width="0dp"
  27. android:layout_weight="1"
  28. android:layout_height="match_parent"
  29. />
  30. <TextView
  31. android:id="@+id/listhide"
  32. android:layout_width="wrap_content"
  33. android:layout_height="match_parent"
  34. android:visibility="gone"
  35. />
  36. <CheckBox
  37. android:focusable="false"
  38. android:clickable="false"
  39. android:id="@+id/listchoice"
  40. android:layout_width="0dp"
  41. android:layout_weight="1"
  42. android:layout_height="match_parent"
  43. />
  44. </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_horizontal"
>
<TextView
android:gravity="center"
android:id="@+id/listid"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:visibility="gone"
/>
<TextView
android:gravity="center"
android:id="@+id/listname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
/>
<TextView
android:gravity="center"
android:id="@+id/listphone"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
/>
<TextView
android:id="@+id/listhide"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="gone"
/>
<CheckBox
android:focusable="false"
android:clickable="false"
android:id="@+id/listchoice"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
/>
</LinearLayout>

3.使用SimpleCursorAdapter绑定数据库与ListView:

代码如下:

[java] view plaincopyprint?
  1. private void getContacts()
  2. {
  3. GetContactsService gs = new GetContactsService(ChooseActivity.this);
  4. Cursor cursor = gs.query("select _id,pname,pnumber,pstate from contacts", null);
  5. //注意:使用SimpleCursorAdapter的话,这个_id是必不可少的!不然一直报错
  6. //所以在前面需要弄一个隐藏的组件来放_id
  7. simpleCursorAdapter = new SimpleCursorAdapter(ChooseActivity.this, R.layout.listitem,
  8. cursor, new String[]{"_id","pname","pnumber","pstate"},
  9. new int[]{R.id.listid,R.id.listname,R.id.listphone,R.id.listhide});
  10. list.setAdapter(simpleCursorAdapter);
  11. }
private void getContacts()
{
GetContactsService gs = new GetContactsService(ChooseActivity.this);
Cursor cursor = gs.query("select _id,pname,pnumber,pstate from contacts", null);
//注意:使用SimpleCursorAdapter的话,这个_id是必不可少的!不然一直报错
//所以在前面需要弄一个隐藏的组件来放_id
simpleCursorAdapter = new SimpleCursorAdapter(ChooseActivity.this, R.layout.listitem,
cursor, new String[]{"_id","pname","pnumber","pstate"},
new int[]{R.id.listid,R.id.listname,R.id.listphone,R.id.listhide});
list.setAdapter(simpleCursorAdapter);
}


注意!!!!使用SimpleCursorAdapter的话,绑定的数据库表中一定要有_id这个字段,或者as _id;

而且在绑定时取出的数据必须包含这个_id项,否则的话会报以下错误!

java.lang.IllegalArgumentException: column '_id' does not exist

4.在OnCreate( )中调用该方法:

在Activity中调用3的getContacts( ),就可以看到我们的已经把数据库的数据显示到ListView上了:

5.点击listview列表项执行的操作:

①为listView设置setOnItemClickListener方法,即点击事件

②点击后要左什么呢?改变checkbox的选中状态,以及统计有多少个选中,然后显示出来

先定义一个用于统计当前选中的复选框数量:

[java] view plaincopyprint?
  1. private int setShow()
  2. {
  3. int num = 0;
  4. for(int i = 0;i < list.getChildCount();i++)
  5. {
  6. LinearLayout layout = (LinearLayout) list.getChildAt(i);
  7. CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
  8. if(cbx.isChecked())num++;
  9. }
  10. return num;
  11. }
 private int setShow()
{
int num = 0;
for(int i = 0;i < list.getChildCount();i++)
{
LinearLayout layout = (LinearLayout) list.getChildAt(i);
CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
if(cbx.isChecked())num++;
}
return num;
}

接着实现点击后复选框选中,以及已选数目的改变:

[java] view plaincopyprint?
  1. list.setOnItemClickListener(new OnItemClickListener() {
  2. @Override
  3. public void onItemClick(AdapterView<?> parent, View view,
  4. int position, long id) {
  5. CheckBox cb = (CheckBox) view.findViewById(R.id.listchoice);
  6. TextView itemhide = (TextView) view.findViewById(R.id.listhide);
  7. TextView itemid = (TextView) view.findViewById(R.id.listid);
  8. int state = Integer.parseInt(itemhide.getText().toString());
  9. //利用这个变量来区分按钮是否选中
  10. state *= -1;
  11. itemhide.setText(state+"");
  12. if(state == 1)cb.setChecked(true);
  13. else cb.setChecked(false);
  14. textshow.setText(setShow()+"项");
  15. }
  16. });
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
CheckBox cb = (CheckBox) view.findViewById(R.id.listchoice);
TextView itemhide = (TextView) view.findViewById(R.id.listhide);
TextView itemid = (TextView) view.findViewById(R.id.listid);
int state = Integer.parseInt(itemhide.getText().toString());
//利用这个变量来区分按钮是否选中
state *= -1;
itemhide.setText(state+"");
if(state == 1)cb.setChecked(true);
else cb.setChecked(false);
textshow.setText(setShow()+"项");
}
});

完成上述代码后运行出现以下效果:

6.全选功能的实现:

就是选中全部的列表项,接着显示数目而已!

[java] view plaincopyprint?
  1. btnall.setOnClickListener(new OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. allflag *= -1;
  5. if(allflag == -1)
  6. {
  7. for(int i = 0;i < list.getChildCount();i++)
  8. {
  9. LinearLayout layout = (LinearLayout) list.getChildAt(i);
  10. CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
  11. cbx.setChecked(true);
  12. btnall.setText("全不选");
  13. textshow.setText(setShow()+"项");
  14. }
  15. }
  16. else if(allflag == 1)
  17. {
  18. for(int i = 0;i < list.getChildCount();i++)
  19. {
  20. LinearLayout layout = (LinearLayout) list.getChildAt(i);
  21. CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
  22. cbx.setChecked(false);
  23. btnall.setText("全选");
  24. textshow.setText(setShow()+"项");
  25. }
  26. }
  27. }
  28. });
     btnall.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
allflag *= -1;
if(allflag == -1)
{
for(int i = 0;i < list.getChildCount();i++)
{
LinearLayout layout = (LinearLayout) list.getChildAt(i);
CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
cbx.setChecked(true);
btnall.setText("全不选");
textshow.setText(setShow()+"项");
}
}
else if(allflag == 1)
{
for(int i = 0;i < list.getChildCount();i++)
{
LinearLayout layout = (LinearLayout) list.getChildAt(i);
CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
cbx.setChecked(false);
btnall.setText("全选");
textshow.setText(setShow()+"项");
}
}
}
});

上述代码实现后的效果:

7.下一步按钮点击触发事件的重写:

在这个按钮事件要完成的工作:

①遍历listview,获取checkbox为选中状态的,将对应联系人id存储到集合中!

②将集合存放到Intent中,it.putIntegerArrayListExtra("ids", checkedId);

代码如下:

[java] view plaincopyprint?
  1. btnnext.setOnClickListener(new OnClickListener() {
  2. public void onClick(View v) {
  3. ArrayList<Integer> checkedId = new ArrayList<Integer>();
  4. for(int i = 0;i < list.getChildCount();i++)
  5. {
  6. LinearLayout layout = (LinearLayout) list.getChildAt(i);
  7. CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
  8. TextView txtid = (TextView) layout.findViewById(R.id.listid);
  9. if(cbx.isChecked())
  10. checkedId.add(Integer.parseInt(txtid.getText().toString()));
  11. }
  12. //跳转到第三个页面,同时把数据存储到intent对象中
  13. Intent it = new Intent(ChooseActivity.this,ThridActivity.class);
  14. it.putIntegerArrayListExtra("ids", checkedId);
  15. startActivity(it);
  16. }
  17. });
     btnnext.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ArrayList<Integer> checkedId = new ArrayList<Integer>();
for(int i = 0;i < list.getChildCount();i++)
{
LinearLayout layout = (LinearLayout) list.getChildAt(i);
CheckBox cbx = (CheckBox) layout.findViewById(R.id.listchoice);
TextView txtid = (TextView) layout.findViewById(R.id.listid);
if(cbx.isChecked())
checkedId.add(Integer.parseInt(txtid.getText().toString()));
}
//跳转到第三个页面,同时把数据存储到intent对象中
Intent it = new Intent(ChooseActivity.this,ThridActivity.class);
it.putIntegerArrayListExtra("ids", checkedId);
startActivity(it);
}
});

恩呢,第二个界面就做好了!本节也到此结束了!

知识点总结:

好了,最后总结下这节中用到的知识点:

1)在LinearLayout中使用weight属性将水平或者竖直方向平分成多份!

2)使用visibility对组件进行隐藏:visible(可见),invisible(不可见,但还占据空间),gone(不可见,也不占空间)

3)SimpleCursorAdapter绑定数据库与ListView需要注意必须要有:_id这个字段或者某字段 as _id;

4)如何统计listview复选框为选中状态的列数,遍历listview!

5)使用intent的putIntegerArrayListExtra存储ArrayList<T>集合类型的数据,传递到另一Activity中!

Android基础整合项目(一) 之节日群发助手part 3

——转载请注明出处:coder-pig


本节引言:

在前面两个章节中我们已经完成了群发助手的读联系人,存取数据库;使用

SimpleCursorAdapter绑定数据库与ListView;实现listview的全选与全不选;

也把需要拨打电话号码的id以list集合的形式通过Intent传送到了第三个界面

今天我们就来完成第三个界面的开发,工作如下:

1)完成第三个Activity的布局

2)解析第二个Activity通过Intent传送过来的List集合

3)读取数据表中的festival表中的节日祝福语,显示到界面上

4)完成切换祝福语的功能

5)完成发送统一祝福语的功能

6)完成发送不同祝福语的功能

7)使用具有列表和带确定按钮的AlertDialog

8)使用SmsManager完成短信的发送

正文:

1.完成第三个Activity的布局:

代码如下:

[html] view plaincopyprint?
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/LinearLayout1"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. tools:context="com.jay.example.festivalsmshelper.MainActivity" >
  8. <LinearLayout
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:orientation="horizontal"
  12. >
  13. <EditText
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:hint="亲爱的"
  17. android:id="@+id/editappellation"
  18. />
  19. <TextView
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:text="XXX,我是"
  23. />
  24. <EditText
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content"
  27. android:hint="小猪"
  28. android:id="@+id/editme"
  29. />
  30. </LinearLayout>
  31. <TextView
  32. android:layout_width="match_parent"
  33. android:layout_height="150dp"
  34. android:id="@+id/textwish"
  35. />
  36. <LinearLayout
  37. android:layout_width="match_parent"
  38. android:layout_height="wrap_content"
  39. android:orientation="horizontal">
  40. <Button
  41. android:layout_width="wrap_content"
  42. android:layout_height="wrap_content"
  43. android:text="切换祝福语"
  44. android:id="@+id/btnchange"
  45. />
  46. <Button
  47. android:layout_width="wrap_content"
  48. android:layout_height="wrap_content"
  49. android:text="发送不同祝福语"
  50. android:id="@+id/btnsendunlike"
  51. />
  52. </LinearLayout>
  53. <LinearLayout
  54. android:layout_width="match_parent"
  55. android:layout_height="wrap_content"
  56. android:orientation="horizontal"
  57. >
  58. <Button
  59. android:layout_width="wrap_content"
  60. android:layout_height="wrap_content"
  61. android:text="发送统一祝福语"
  62. android:id="@+id/btnsendlike"
  63. />
  64. <Button
  65. android:layout_width="wrap_content"
  66. android:layout_height="wrap_content"
  67. android:text="返回"
  68. android:id="@+id/btnback"
  69. />
  70. </LinearLayout>
  71. </LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.jay.example.festivalsmshelper.MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="亲爱的"
android:id="@+id/editappellation"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="XXX,我是"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="小猪"
android:id="@+id/editme"
/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="150dp"
android:id="@+id/textwish"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换祝福语"
android:id="@+id/btnchange"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送不同祝福语"
android:id="@+id/btnsendunlike"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送统一祝福语"
android:id="@+id/btnsendlike"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:id="@+id/btnback"
/>
</LinearLayout>
</LinearLayout>

2.解析第二个Activity传送过来的List集合:

直接用list存储即可,增强for循环可以去掉,只是用来确认传过来的集合是否有数据,

从而避免空指针问题的出现

[java] view plaincopyprint?
  1. Intent it = getIntent();
  2. final List<Integer> list = it.getIntegerArrayListExtra("ids");
  3. int i = 1;
  4. //下面这个语句用于查看是否有传值过来,传了什么值,通常用log.?来跟踪错误
  5. for(Integer j:list)
  6. {
  7. System.out.println(j);
  8. }
Intent it = getIntent();
final List<Integer> list = it.getIntegerArrayListExtra("ids");
int i = 1;
//下面这个语句用于查看是否有传值过来,传了什么值,通常用log.?来跟踪错误
for(Integer j:list)
{
System.out.println(j);
}

3.读取数据库表中的festival表的祝福语并显示

简单的一条查询语句即可:

[java] view plaincopyprint?
  1. sql = "select detail from festival where sentence_id = " + num+"";
  2. textwish.setText(getWish(sql));
sql = "select detail from festival where sentence_id = " + num+"";
textwish.setText(getWish(sql));

另外因为我们的操作很多都要查询数据库,就直接写到一个方法中getWish()

[java] view plaincopyprint?
  1. private String getWish(String sql)
  2. {
  3. String wish = null;
  4. GetContactsService gcs = new GetContactsService(ThridActivity.this);
  5. Cursor curosr =gcs.query(sql, null);
  6. curosr.moveToFirst();
  7. wish = curosr.getString(0);
  8. curosr.close();
  9. return wish;
  10. }
private String getWish(String sql)
{
String wish = null;
GetContactsService gcs = new GetContactsService(ThridActivity.this);
Cursor curosr =gcs.query(sql, null);
curosr.moveToFirst();
wish = curosr.getString(0);
curosr.close();
return wish;
}

ps:num是一个整数1-10都可以,看数据库表的记录数决定的

4.完成祝福语的切换功能:

其实这里就是简单的改变上面那个num的数字而已,自增++

然后等于十的时候把num重置为1即可

[java] view plaincopyprint?
  1. btnchange.setOnClickListener(new OnClickListener() {
  2. public void onClick(View v) {
  3. if(num == 10)num = 1;
  4. else ++num;
  5. sql = "select detail from festival where sentence_id = " + num+"";
  6. textwish.setText(getWish(sql));
  7. }
  8. });
     btnchange.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(num == 10)num = 1;
else ++num;
sql = "select detail from festival where sentence_id = " + num+"";
textwish.setText(getWish(sql));
}
});

5)完成发送统一祝福语的功能:

就是给每个联系人发送相同的短信,这里的话,先读取传过来的集合获取id

然后根据id读取Contacts表中id对应的联系人名称,电话号码;

将这两个组合到一起,作为对话框的列表项的资源数组

还需要创建一个带列表的对话框,添加一个确定按钮

代码:

[java] view plaincopyprint?
  1. btnsendlike.setOnClickListener(new OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. String ids = "";
  5. //将list集合中的数据取出来,结果可能是:7,8,9,这样的
  6. for(Integer j:list)
  7. {
  8. ids = ids + j + ",";
  9. }
  10. //去掉小尾巴","直接去掉最后一位即可
  11. ids = ids.substring(0, ids.length()-1);
  12. System.out.println(ids);
  13. //需要取出Contacts表中的联系人信息,用于等下对话框内容显示以及发送短信时
  14. sql = "select * from contacts where _id in("+ids+")";
  15. System.out.println(sql);
  16. List<Map<String,String>> lc = getContacts(sql);
  17. //取出集合中的元素放到字符串数据中
  18. //判断需创建的数组的长度
  19. int length = 0;
  20. for(Map<String,String> mp:lc)
  21. {
  22. length++;
  23. }
  24. final int lg = length;
  25. String name[] = new String[length];
  26. String number[] = new String[length];
  27. String show[] = new String[length];
  28. final String finumber[] = number;
  29. final String finame[] = name;
  30. int i = 0;
  31. for(Map<String,String> mp:lc)
  32. {
  33. name[i] = mp.get("name");
  34. number[i] = mp.get("number");
  35. Log.i("name[i]", name[i]);
  36. Log.i("number[i]", number[i]);
  37. i++;
  38. }
  39. for(int o = 0;o < i;o++)
  40. {
  41. show[o] = name[o] + ":" + number[o];
  42. Log.i("show[o]", show[o]);
  43. }
  44. //弹出确认的对话框:
  45. builder = new AlertDialog.Builder(ThridActivity.this);
  46. builder.setTitle("统一发送祝福语模式\n请确认发送人员:");
  47. builder.setIcon(R.drawable.ic_launcher);
  48. builder.setItems(show,null);
  49. builder.setPositiveButton("确定发送", new DialogInterface.OnClickListener()
  50. {
  51. @Override
  52. public void onClick(DialogInterface dialog, int which) {
  53. for(int p = 0;p < lg;p++)
  54. {
  55. String num = finumber[p];
  56. String wish = editappellation.getText().toString() +  finame[p] + "我是"+
  57. editme.getText().toString() +
  58. textwish.getText().toString();
  59. sendMessage(num, wish);
  60. }
  61. }
  62. });
  63. alert = builder.create();
  64. alert.show();
  65. }
  66. });
btnsendlike.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String ids = "";
//将list集合中的数据取出来,结果可能是:7,8,9,这样的
for(Integer j:list)
{
ids = ids + j + ",";
}
//去掉小尾巴","直接去掉最后一位即可
ids = ids.substring(0, ids.length()-1);
System.out.println(ids);
//需要取出Contacts表中的联系人信息,用于等下对话框内容显示以及发送短信时
sql = "select * from contacts where _id in("+ids+")";
System.out.println(sql);
List<Map<String,String>> lc = getContacts(sql);
//取出集合中的元素放到字符串数据中
//判断需创建的数组的长度
int length = 0;
for(Map<String,String> mp:lc)
{
length++;
}
final int lg = length;
String name[] = new String[length];
String number[] = new String[length];
String show[] = new String[length];
final String finumber[] = number;
final String finame[] = name;
int i = 0;
for(Map<String,String> mp:lc)
{
name[i] = mp.get("name");
number[i] = mp.get("number");
Log.i("name[i]", name[i]);
Log.i("number[i]", number[i]);
i++;
}
for(int o = 0;o < i;o++)
{
show[o] = name[o] + ":" + number[o];
Log.i("show[o]", show[o]);
}
//弹出确认的对话框:
builder = new AlertDialog.Builder(ThridActivity.this);
builder.setTitle("统一发送祝福语模式\n请确认发送人员:");
builder.setIcon(R.drawable.ic_launcher);
builder.setItems(show,null);
builder.setPositiveButton("确定发送", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which) {
for(int p = 0;p < lg;p++)
{
String num = finumber[p];
String wish = editappellation.getText().toString() +  finame[p] + "我是"+
editme.getText().toString() +
textwish.getText().toString();
sendMessage(num, wish);
}
}
});
alert = builder.create();
alert.show();
}
});

6)创建发送短信的方法:

[java] view plaincopyprint?
  1. private void sendMessage(String number,String message)
  2. {
  3. SmsManager.getDefault().sendTextMessage(number,
  4. null, message, null, null);
  5. Toast.makeText(getApplicationContext(), "发送成功", Toast.LENGTH_SHORT).show();
  6. //在模拟器环境中我们需要查看发出的短信内容或者真机调试时不想浪费短信钱
  7. //就使用log.i查看发出的短信内容即可
  8. Log.i("sendMessage", number+message);
  9. }
 private void sendMessage(String number,String message)
{
SmsManager.getDefault().sendTextMessage(number,
null, message, null, null);
Toast.makeText(getApplicationContext(), "发送成功", Toast.LENGTH_SHORT).show();
//在模拟器环境中我们需要查看发出的短信内容或者真机调试时不想浪费短信钱
//就使用log.i查看发出的短信内容即可
Log.i("sendMessage", number+message);
}

另外,使用上述方法发送短信,你的手机是不会保留发送的信息记录的;

其实就是后台发送短信!

7)好了,完成5,6步后程序基本成型了:

完成前面6步后,程序已经可以完成基本功能了:

效果如下:

接着查看我们的Logcat,可以看到发送的信息内容:

8)最后再完成随机祝福语部分

就是随机给不同的人发送不同内容的短信:

其实这里和上面那个部分是大同小异的,仅仅是修改发送短信时

的祝福语内容,使用随机数决定发送的祝福语而已,仅仅需要添加下述代码即可:

1)取出Festival表中的detail字段的所有记录,存储到字符串数组中

[java] view plaincopyprint?
  1. //将所有的祝福语短信存储到字符串数组中
  2. String sql = "select detail from festival";
  3. String[] showmsg = new String[10];
  4. GetContactsService gcService = new GetContactsService(ThridActivity.this);
  5. Cursor curosr =gcService.query(sql, null);
  6. int s = 0;
  7. curosr.moveToFirst();
  8. while(curosr.moveToNext())
  9. {
  10. showmsg[s] = curosr.getString(0);
  11. s++;
  12. }
  13. final String[] fishowmsg = showmsg;
//将所有的祝福语短信存储到字符串数组中
String sql = "select detail from festival";
String[] showmsg = new String[10];
GetContactsService gcService = new GetContactsService(ThridActivity.this);
Cursor curosr =gcService.query(sql, null);
int s = 0;
curosr.moveToFirst();
while(curosr.moveToNext())
{
showmsg[s] = curosr.getString(0);
s++;
}
final String[] fishowmsg = showmsg; 

2)使用随机数,随机的取出祝福语

[java] view plaincopyprint?
  1. for(int p = 0;p < lg;p++)
  2. {
  3. String num = finumber[p];
  4. //只需要修改输出时的祝福语内容即可
  5. int randow =  (int) (Math.random() * 10);
  6. String wish = editappellation.getText().toString() +  finame[p] + "我是"+
  7. editme.getText().toString() +
  8. fishowmsg[randow];
  9. sendMessage(num, wish);
  10. }
for(int p = 0;p < lg;p++)
{
String num = finumber[p];
//只需要修改输出时的祝福语内容即可
int randow =  (int) (Math.random() * 10);
String wish = editappellation.getText().toString() +  finame[p] + "我是"+
editme.getText().toString() +
fishowmsg[randow];
sendMessage(num, wish);
}

运行截图:

截至之当前的项目代码:

代码下载

知识点总结:

1)解析Intent中存储的list集合:

Intent it = getIntent();
final List<Integer> list = it.getIntegerArrayListExtra("ids");

2)SQLite数据库的相关操作,以及cursor的使用

切忌一点,使用cursor一定要调用cursor.moveToFirst()不然会报错哦!

另外可以调用moveToNext()可以使游标后移!可使用getXxx获取不同类型的数据

3)使用SmsManager.getDefault().sendTextMessage(number, null, message, null, null);

发送短信

4)生成1~10内的随机整数:int randow =  (int) (Math.random() * 10); 

好了,节日群发助手这个项目开发就到这里了,app仅仅是具有雏形,UI和代码都没有

优化,存在一定的冗余和bug,各位学员在自己编写的过程中可以自行的修改或者优化

本文的初衷是帮助各位初学者巩固相关的知识点的!后续会推出类似的知识点整合

项目,敬请关注,谢谢

当然有时间也会修改下这个app,正如大牛所说的,改下UI或许会是个好的app

Android基础整合项目之节日群发助手相关推荐

  1. Android基础整合项目之节日群发助手(二)

    Android基础整合项目(一) 之节日群发助手part 2 --转载请注明出处:coder-pig 本节引言: 在上一节中我们已经做出了我们群发助手的第一个界面以及完成了联系人的读取以及数据库的 录 ...

  2. Android基础——项目的文件结构(三)

    Android基础--项目的文件结构(三) 代码源文件夹与资源文件夹 [注]此项目文件结构仅限于Android Studio下的Android项目!!! 在一个Android项目中,代码源文件夹有4个 ...

  3. Android Studio实现学生信息管理系统,基础入门项目

    文章目录 一.需求分析 二.开发环境 三.详细设计 3.1 项目结构 3.2 数据库 3.3 登录和注册 3.4 增删改查 四.项目演示 五.项目源码 一.需求分析 该学生信息管理系统具有添加学生信息 ...

  4. Android基础知识【项目实训-实现二级导航“今日活动”及读取数据库】【5】

    [该项目实训是Android基础知识的一个综合练习,特别提示:项目中会用到一些图片素材,都是随意整理的,稍后会上传一个资源,包含该事项项目的基本功能,也含有图片素材] [项目题目]:校园订餐App设计 ...

  5. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第三章:简单控件

    第 3 章 简单控件 本章介绍了App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图.容纳视图的常用布局.响应点击的按钮控件.显示图片的图像视图等.然后结合本章所学的知识,演示了一个实战项 ...

  6. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第六章:数据存储

    第 6 章 数据存储 本章介绍Android 4种存储方式的用法,包括共享参数SharedPreferences.数据库SQLite.存储卡文 件.App的全局内存,另外介绍Android重要组件-应 ...

  7. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第五章:中级控件

    第 5 章 中级控件 本章介绍App开发常见的几类中级控件的用法,主要包括:如何定制几种简单的图形.如何使用几种选择按钮.如何高效地输入文本.如何利用对话框获取交互信息等,然后结合本章所学的知识,演示 ...

  8. Android基础——项目的文件结构(二)

    Android基础--项目的文件结构(二) AndroidManifest.xml文件分析 [注]此项目文件结构仅限于Android Studio下的Android项目!!! 在一个Android项目 ...

  9. 重学Android基础系列篇(五):Android虚拟机指令

    前言 本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~ [非商业用途,如有侵权,请告 ...

  10. 手把手教你扩展个人微信号(2)(微信控制器、群发助手、好友删除检测)...

    现在的日常生活已经离不开微信,本文将会抛砖引玉演示如何使用Python调用微信API做一些有意思的东西. 看完这一系列教程,你就能从头开始实现自己关于微信的想法. 本文为教程的第二部分,主要以微信控制 ...

最新文章

  1. 深度学习未来的三种方式
  2. 如何用js获取外联css,内联外联CSS和JS
  3. 数据结构:关于AVL树的平衡旋转详解
  4. BZOJ-2190-仪仗队-SDOI2008-欧拉函数
  5. 在C语言中如何让常量起作用,解析C语言中如何正确使用const
  6. JavaScript eval
  7. git rebase 工作流
  8. 管理感悟:计划是给谁看的
  9. ROST情感分析的语法规则_用c语言手搓一个600行的类c语言解释器: 给编程初学者的解释器教程(4)- 语法分析1...
  10. 2021微信网页跳转APP
  11. R语言如何做NMDS分析
  12. NVIDIA NGC镜像使用笔记
  13. 不良资产证券化是什么意思
  14. 正交试验设计例题及答案_【正交试验设计法是】试验设计与分析试题及答案
  15. N-gram模型(基于词表)
  16. Anaconda3安装tensorflow踩坑记录
  17. 一个有用的命令jcmd
  18. Normalization如何解决梯度消失
  19. blender中文三维立体文字制作方法
  20. 中国制造2025与机器人——苏大机电学院院长谈机器人发展趋势

热门文章

  1. 【干货】数据结构与算法该如何正确学习?(书籍\视频\网站都推荐了)
  2. vue 使用html2canvas实现图片合成,将两张图片合成一张,并下载海报
  3. 九度题目1341:艾薇儿的演唱会
  4. 基于阿里云和Arduino的化学环境系统检测,支持钉钉机器人告警(MQ2、MQ3、MQ7、DHT11 完整源码以及实现步骤)
  5. “大狼狗加密专家”使用简介
  6. python实现税后工资_Python实现扣除个人税后的工资计算器示例
  7. FFmpeg进阶: 给视频添加背景音乐
  8. 趣味计算机专业比赛,你hua我猜 以梦为马——计算机科学系第三届你画我猜趣味比赛...
  9. 房地产业务学习(04)-房企信息化:谁忽悠了谁?
  10. Filter过滤器及其作用