Android数据存储_数据存储的几种方式
Android的数据存储:
1.SharePreference。
2.内置的SQLite数据库。
3.ContentProvider实现数据共享。
4.Networks。
5.File IO。
SharePreference:
保存应用程序的各种配置信息,存储的数据一般只能供本应用程序调用,不对外共享。
1.调用getSharePreferences()方法创建对象;
2.调用edit()方法获得Editor对象,供读写数据:getXxx(),putXxx(),remove(),commit()。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 按下btn_write时,存放SHARED_MSGi,i=1,2,3,4,5到SETTING_PREF內容文件 */ btn_write.setOnClickListener(new Button.OnClickListener() { public void onClick(View v){ int int2 = Integer.parseInt(mEditText02.getText().toString()); long long3 = Long.parseLong(mEditText03.getText().toString()); float float4 = Float.parseFloat(mEditText04.getText().toString()); boolean boolean5 = true; if (mRadioButton01.isChecked()){ boolean5 = true; } else if (mRadioButton02.isChecked()) { boolean5 = false; } SharedPreferences settings = getSharedPreferences(SETTING_PREF, MODE_PRIVATE); settings.edit() .putString(SHARED_MSG1, mEditText01.getText().toString()) .putInt(SHARED_MSG2, int2) .putLong(SHARED_MSG3, long3) .putFloat(SHARED_MSG4, float4) .putBoolean(SHARED_MSG5, boolean5) .commit(); } }); /** * 按下btn_read时,读取SETTING_PREF內容文件的SHARED_MSGi,i=1,2,3,4,5 */ btn_read.setOnClickListener(new Button.OnClickListener() { public void onClick(View v){ SharedPreferences settings = getSharedPreferences(SETTING_PREF, 0); String msg1 = settings.getString(SHARED_MSG1, ""); mEditText01.setText(msg1); int defint2 = 0; int msg2_int = settings.getInt(SHARED_MSG2, defint2); String msg2 = String.valueOf(msg2_int); mEditText02.setText(msg2); long deflong3 = 0; long msg3_long = settings.getLong(SHARED_MSG3, deflong3); String msg3 = String.valueOf(msg3_long); mEditText03.setText(msg3); float deffloat4 = 0; float msg4_float = settings.getFloat(SHARED_MSG4, deffloat4); String msg4 = String.valueOf(msg4_float); mEditText04.setText(msg4); boolean defboolean5 = true; boolean msg5_boolean = settings.getBoolean(SHARED_MSG5, defboolean5); if (msg5_boolean) { mRadioButton01.setChecked(true); mRadioButton02.setChecked(false); mRadioButton03.setChecked(false); } else { mRadioButton01.setChecked(false); mRadioButton02.setChecked(true); mRadioButton03.setChecked(false); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mEditText01 = (EditText)findViewById(R.id.EditText01); mEditText02 = (EditText)findViewById(R.id.EditText02); /** * 开机时,自SETTING_FILE內容文件取得NAME_MSG、MOBILE_MSG,并显示在EditText01和EditText02 */ SharedPreferences settings = getSharedPreferences(SETTING_FILE, 0); String name_msg = settings.getString(NAME_MSG, "null"); String mobile_msg = settings.getString(MOBILE_MSG, "null"); mEditText01.setText(name_msg); mEditText02.setText(mobile_msg); } @Override protected void onStop(){ super.onStop(); Toast.makeText(this, "onStop(): SharedPreferences存储NAME_MSG、MOBILE_MSG到SETTING_FILE", Toast.LENGTH_SHORT).show(); /** * 离开时,在onStop()程序中存放NAME_MSG、MOBILE_MSG到SETTING_FILE內容文件 */ SharedPreferences settings = getSharedPreferences(SETTING_FILE, 0); settings.edit() .putString(NAME_MSG, mEditText01.getText().toString()) .putString(MOBILE_MSG, mEditText02.getText().toString()) .commit(); }
Android内置的SQLite数据库:
1.Android提供了SQLiteDatabase代表一个数据库,应用程序可通过创建SQLiteDatabase对象来操作数据库.
其包含的静态方法:
static SQLiteDatabase.openDatabase();
.openOrCreateDatabase():打开创建
execSQL():执行SQL语句.
beginTransaction(); endTransaction(); inTransaction(); 事务处理
insert(),update(),delete(),rawQuery(),Cursor,query()
2.Android SDK的tools目录下还提供了sqlite3.exe工具,数据库命令行管理工具.
3.数据库帮助类SQLiteOpenHelper操作数据库步骤:
[SQLiteOpenHelper帮助类用来初始化数据库实例,而真正的instance数据库实例由SQLiteDatabase创建,当第一次执行时则调用onCreate()方法]
[SQLiteOpenHelper包装省略了SQLiteDatabase连接数据库的过程,助手类]
(1)创建一个类,继承SQLiteOpenHelper抽象类,重写构造函数传入Context上下文,复写抽象方法:
onCreate():当第一次创建数据库时回调该方法.
onUpgrade()当数据库版本更新时回调该方法
(2)调用SQLiteOpenHelper的getReadableDatabase()或getWriteableDatabase()方法,
这两个方法可封装于自定义的openDatabase()方法中,调用则会创建数据库或打开数据库连接。
这两个方法打开数据库连接后会获得一个用于操作数据库的SQLiteDatabase对象,就可以开始对数据库的增删查改操作。
[getReadableDatabase()或getWriteableDatabase()方法调用后当数据库不存在时会自动触发onCreate()方法创建数据库]
(3)调用SQLiteDatabase的方法执行SQL语句操作数据库。
(4)处理SQL语句执行后返回的结果。
(4)调用.close()关闭数据库连接。
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 本范例说明数据库的建立,数据添加,更新,删除,检索 * @author Administrator * */ public class SQLiteTest extends Activity { OnClickListener listener_add = null;//监听器类 OnClickListener listener_update = null; OnClickListener listener_delete = null; OnClickListener listener_clear = null; Button button_add; Button button_update; Button button_delete; Button button_clear; DBConnection dbhelper; //DBConnection为自定义内部类,extends SQLiteOpenHelper public int id_this; public interface UserSchema { //定义接口包装数据库表名和字段名 String TABLE_NAME = "Users"; //Table Name String ID = "_id"; //ID String USER_NAME = "user_name"; //User Name String ADDRESS = "address"; //Address String TELEPHONE = "telephone"; //Phone Number String MAIL_ADDRESS = "mail_address"; //Mail Address } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final EditText mEditText01 = (EditText)findViewById(R.id.EditText01); final EditText mEditText02 = (EditText)findViewById(R.id.EditText02); final EditText mEditText03 = (EditText)findViewById(R.id.EditText03); final EditText mEditText04 = (EditText)findViewById(R.id.EditText04); dbhelper = new DBConnection(this); final SQLiteDatabase db = dbhelper.getWritableDatabase(); final String[] FROM = { UserSchema.ID, UserSchema.USER_NAME, UserSchema.TELEPHONE, UserSchema.ADDRESS, UserSchema.MAIL_ADDRESS }; Cursor c = db.query(UserSchema.TABLE_NAME, new String[] {UserSchema.USER_NAME} , null, null, null, null, null); //查询Users表,读取所有的user_name,保存在游标Cursor中 /*query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) * 第一个参数为要查询的数据库实例。 * 第二个参数是一个字符串数组,里边的每一项代表了需要返回的列名。属性名 * 第三个参数相当于SQL语句中的where部分。 * 第四个参数是一个字符串数组,里边的每一项依次替代在第三个参数中出现的问号(?)。 * 第五个参数相当于SQL语句当中的groupby部分。 * 第六个参数相当于SQL语句当中的having部分。 * 第七个参数描述是怎么进行排序。 * 第八个参数相当于SQL当中的limit部分,控制返回的数据的个数。*/ c.moveToFirst(); CharSequence[] list = new CharSequence[c.getCount()]; /*CharSequence是char的包装接口,不能使用new来进行赋值, * 可以定义:CharSequence cs="hello"; * 不能定义:CharSequence cs=new CharSequence("hello"); * 但此处定义的是对象数组,还没有实例化,元素为null*/ for (int i = 0; i < list.length; i++) { list[i] = c.getString(0); c.moveToNext(); } c.close(); //关闭Cursor /** * list */ Spinner spinner = (Spinner)findViewById(R.id.Spinner01); //取得所有数据的USER_NAME,放置在list[]上 spinner.setAdapter(new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, list)); spinner.setOnItemSelectedListener(new OnItemSelectedListener(){ //在Spinner下拉列表上选定查询的数据,显示所有数据在画面上 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String user_name = ((Spinner)parent).getSelectedItem().toString(); Cursor c = db.query("Users", FROM , //查询User表,读取符合变量user_name的所有数据(FROM) "user_name='" + user_name + "'", null, null, null, null); c.moveToFirst(); id_this = Integer.parseInt(c.getString(0)); //将查询到的个人数据的ID赋值给id_this,以便以后更新或检索时用 String user_name_this = c.getString(1); //读取所有个人数据 String telephone_this = c.getString(2); String address_this = c.getString(3); String mail_address_this = c.getString(4); c.close(); //关闭Cursor mEditText01.setText(user_name_this); mEditText02.setText(telephone_this); mEditText03.setText(address_this); mEditText04.setText(mail_address_this); } public void onNothingSelected(AdapterView<?> parent) { } }); /** * 按下[Add]按钮时,新增一行数据 */ listener_add = new OnClickListener() { public void onClick(View v) { ContentValues values = new ContentValues();//创建ContentValues类的对象,存储键值对,进行数据库操作 values.put(UserSchema.USER_NAME, mEditText01.getText().toString()); values.put(UserSchema.TELEPHONE, mEditText02.getText().toString()); values.put(UserSchema.ADDRESS, mEditText03.getText().toString()); values.put(UserSchema.MAIL_ADDRESS, mEditText04.getText().toString()); SQLiteDatabase db = dbhelper.getWritableDatabase(); //创建数据库连接 db.insert(UserSchema.TABLE_NAME, null, values); //插入数据到数据库 db.close(); //关闭数据库 onCreate(savedInstanceState); //重新执行本程序,即实现建立新的下拉列表和数据 } }; /** * 按下[Update]按钮时,更新一行数据 */ listener_update = new OnClickListener() { public void onClick(View v) { ContentValues values = new ContentValues(); values.put(UserSchema.USER_NAME, mEditText01.getText().toString()); values.put(UserSchema.TELEPHONE, mEditText02.getText().toString()); values.put(UserSchema.ADDRESS, mEditText03.getText().toString()); values.put(UserSchema.MAIL_ADDRESS, mEditText04.getText().toString()); String where = UserSchema.ID + " = " + id_this; SQLiteDatabase db = dbhelper.getWritableDatabase(); db.update(UserSchema.TABLE_NAME, values, where ,null);//以where子句查询到该行数据并以values的值更新 db.close(); onCreate(savedInstanceState); } }; /** * 按下[Delete]按钮时,刪除一行数据 */ listener_delete = new OnClickListener() { public void onClick(View v) { String where = UserSchema.ID + " = " + id_this; SQLiteDatabase db = dbhelper.getWritableDatabase(); db.delete(UserSchema.TABLE_NAME, where ,null);//以where子句查询到该行数据并删除 db.close(); onCreate(savedInstanceState); } }; /** * 按下[Clear]按钮时,清空编辑框 */ listener_clear = new OnClickListener() { public void onClick(View v) { mEditText01.setText(""); mEditText02.setText(""); mEditText03.setText(""); mEditText04.setText(""); } }; //设定BUTTON0i,i=1,2,3,4的OnClickListener button_add = (Button)findViewById(R.id.Button01); button_add.setOnClickListener(listener_add); button_update = (Button)findViewById(R.id.Button02); button_update.setOnClickListener(listener_update); button_delete = (Button)findViewById(R.id.Button03); button_delete.setOnClickListener(listener_delete); button_clear = (Button)findViewById(R.id.Button04); button_clear.setOnClickListener(listener_clear); } /** * 助手类,用以创建数据库连接 * @author Administrator * */ public static class DBConnection extends SQLiteOpenHelper { private static final String DATABASE_NAME = "PhoneBookDB"; private static final int DATABASE_VERSION = 1; private DBConnection(Context ctx) { super(ctx, DATABASE_NAME, null, DATABASE_VERSION); } public void onCreate(SQLiteDatabase db) { //创建TABLE表Users String sql = "CREATE TABLE " + UserSchema.TABLE_NAME + " (" + UserSchema.ID + " INTEGER primary key autoincrement, " + UserSchema.USER_NAME + " text not null, " + UserSchema.TELEPHONE + " text not null, " + UserSchema.ADDRESS + " text not null, " + UserSchema.MAIL_ADDRESS + " text not null "+ ");"; //Log.i("haiyang:createDB=", sql); db.execSQL(sql); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 本范例介绍当有大量输入数据时,如何建立一个SQLite数据库并将所有数据保存入库 * 如何检索关联数据库 * 添加数据库的事务处理 * @author Administrator * */ public class SQLite extends Activity { private DatabaseHelper helper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); helper = new DatabaseHelper(this); //DatabaseHelper自定义助手类建立数据库和相应的表:StudentDB;students,courses; final SQLiteDatabase db = helper.getReadableDatabase(); //创建数据库连接,返回SQLiteDatabase对象 /*----------在Student表中检索所有的student_no,将查询结果保存在list中,绑定在Spinner上显示----------*/ Cursor c = db.query("students", new String[] {"student_no"} , null, null, null, null, null); //检索查询student_no,返回Cursor c.moveToFirst(); CharSequence[] list = new CharSequence[c.getCount()]; //CharSequence[]数组 for (int i = 0; i < list.length; i++) { list[i] = c.getString(0); //将student_no数据保存在list[]中 c.moveToNext(); } c.close(); //关闭Cursor Spinner spinner = (Spinner)findViewById(R.id.Spinner01); spinner.setAdapter(new ArrayAdapter<CharSequence>(this , android.R.layout.simple_spinner_item, list)); //将list绑定在Spinner上显示 spinner.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String student_no = ((Spinner)parent).getSelectedItem().toString();//获取被选择的student_no /*--------在Student表中由student_no查询student_name,并将查询结果显示在textView上----------*/ Cursor c; c = db.query("students", new String[] {"student_name"} , "student_no='" + student_no + "'", null, null, null, null); c.moveToFirst(); String student_this = c.getString(0); c.close(); TextView textView = (TextView)findViewById(R.id.TextView01); textView.setText(student_this); /*---在Course表中由student_no查询student_name,并将查询结果保存在list[]中,绑定在ListView上显示---*/ c = db.query("courses", new String[] {"course_name"} , "student_no='" + student_no + "'", null, null, null, null); c.moveToFirst(); CharSequence[] list = new CharSequence[c.getCount()]; for (int i = 0; i < list.length; i++) { list[i] = c.getString(0); c.moveToNext(); } c.close(); ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(SQLite.this , android.R.layout.simple_list_item_1, list); ListView listView = (ListView)findViewById(R.id.ListView01); listView.setAdapter(adapter); } public void onNothingSelected(AdapterView<?> parent) { } }); } @Override protected void onDestroy() { super.onDestroy(); helper.close(); //Activity销毁前关闭数据库连接 } /*-------------------自定义助手类继承SQLiteOpenHelper用于建立数据库和相应的表-------------------------*/ class DatabaseHelper extends SQLiteOpenHelper { //SQLiteOpenHelper-建立数据库StudentDB和Table:students,Table:courses private static final String DATABASE_NAME = "StudentDB"; private static final int DATABASE_VERSION = 1; //Table:students的数据 private String[][] STUDENTS = { {"A-123","Macoto Lin"}, {"B-456","Hatusko Ueno"}, {"C-789","Wilson Lin"}, }; //Table:courses的数据 private String[][] COURSES = { {"A-123","Japanese"}, {"A-123","Computer"}, {"A-123","English"}, {"B-456","English"}, {"B-456","Computer"}, {"C-789","Computer"}, }; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); //此处创建数据库"StudentDB" } @Override public void onCreate(SQLiteDatabase db) { db.beginTransaction(); //此处加入事务处理Transaction try { SQLiteStatement stmt; //SQLiteStatement /*Statement是Java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。 */ String sql01 = "create table students (student_no text primary key, student_name text not null);"; db.execSQL(sql01); //执行SQL语句,创建Student表 stmt = db.compileStatement("insert into students values (?, ?);"); /*用compileStatement方法封装SQL语句,可以重复编译SQL语句, * 用?作为参数可以将后续数据连结进来,连结方式: * bindString连结字符串,bindLong连接数据 * 此处用for循环,一行一行连接数据,再一行一行执行SQL语句*/ for (String[] studentname : STUDENTS) { stmt.bindString(1, studentname[0]); stmt.bindString(2, studentname[1]); stmt.executeInsert(); } String sql02 = "create table courses (student_no text not null, course_name text not null);"; db.execSQL(sql02); //创建courses表 stmt = db.compileStatement("insert into courses values (?, ?);"); for (String[] coursename : COURSES) { stmt.bindString(1, coursename[0]); stmt.bindString(2, coursename[1]); stmt.executeInsert(); } db.setTransactionSuccessful(); //调用该方法,当处理数据不完整时可将数据回滚 } finally { db.endTransaction(); //关闭事务 } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } }
ContentProvider实现数据共享:
1.ContentProvider是不用应用程序之间进行数据交换的标准API,
ContentProvider提供存取数据的统一接口,使用它可实现在不同应用程序之间共享数据.
应用程序ContentResolver就犹如"网站",以URL的形式对外"暴露"数据.,允许其它应用程序访问和修改数据. [~~数据库操作]
Android为常见的一些数据提供了ContentProvider. [---主要是运用这些内置的]
2.URL:统一资源标识符
Android提供的ContentProvider都存放在android.provider包中.
ContentProvider提供的方法:insert(),delete(),update(),query(),getType().onCreate().
3.实现ContentProvider步骤:
(1)定义一个CONTENT_URI常量
(2)定义一个类,继承ContentProvider类
(3)在AndroidManifest.xml文件中注册<provider>
(4)实现所需的方法.
4.ContentProvider数据在Android中是以表的形式存在的-----数据库.
Cursor:游标---query查询,迭代输出查询结果.
uri.parse():将字符串转换成uri----uriMatcher:匹配uri的工具类.
5.操作ContentProvider所暴露的数据:
(1)由getContentProvider()方法来获取ContentResolver对象.
(2)调用ContentResolver方法操作数据:insert,delete,update,query
6.监听ContentProvider数据改变:(Android提供的ContentObserver基类)
(1)创建一个类,继承ContentObserver类
(2)重写该基类所定义的onChange()方法
(3)向指定Uri注册ContentObserver监听器:registerContentObserver(....);
例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<provider android:name="TestProvider" android:authorities="com.example.android.provider.testprovider" />
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 内容提供器Content Providers的构建:建立一个Sqlite数据库系统来存储和管理数据,用SQLiteDatabase管理数据库 * 1。创建一个类,继承ContentProviders基类 * 2。在AndroidManifest.xml中注册这个ContentProviders */ public class TestProvider extends ContentProvider { DatabaseHelper databaseHelper; //自定义内部类DatabaseHelper创建数据库和表 /*----复写extends ContentProvider的方法,采用ContentProviders方式操作数据库---------*/ @Override public boolean onCreate() { databaseHelper = new DatabaseHelper(getContext()); return true; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); //打开数据库连接 db.insert("test", null, values); //操作数据库 return null; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = databaseHelper.getReadableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables("test"); Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, null); return c; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public String getType(Uri uri) { return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } /*------------------DatabaseHelper extends SQLiteOpenHelper建立test.db和Table:test--------------------*/ private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, "test.db", null, 1); //调用构造方法创建数据库test.db } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE test (" + BaseColumns._ID + " INTEGER PRIMARY KEY," + "name TEXT," + "description TEXT" + ");"); //执行SQL语句创建表test } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS test"); onCreate(db); } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * Application A——————ContentProviders————Application B's Database * 内容提供器ContentProviders公开数据的方法 * 本范例直接在程序内生产测试用的数据,然后检索存储在ContentProviders数据库内的所有行,并用列表字段显示出检索结果 */ public class ProviderTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String struri = "content://com.example.android.provider.testprovider"; //程序就是通过这个URI找到内容提供器ContentProvider Uri uri = Uri.parse(struri); //将struri字符串转换成uri getIntent().setData(uri); //设置当前活动程序Activity接口数据的Uri Uri uri_test = getIntent().getData(); //取得当前活动程序Activity接口数据的Uri,并定义成Uri类变量uri_test ContentValues values = new ContentValues(); values.put("name", "Macoto"); values.put("description", "0932-158983"); getContentResolver().insert(uri_test, values); //采用ContentProviders方式添加数据1 values.put("name", "Ming"); values.put("description", "0932-123456"); getContentResolver().insert(uri_test, values); //采用ContentProviders方式添加数据2 Cursor cur = managedQuery(uri_test, null, null, null, null); //采用ContentProviders方式检索存储在数据库内的所有行.有两种方法,ContentResolver.query()和Activity.managedQuery() cur.moveToFirst(); ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(); Map<String, Object> item; for (int i = 0; i < cur.getCount(); i++) { item = new HashMap<String, Object>(); item.put("column00", cur.getString(0)); item.put("column01", cur.getString(1)); item.put("column02", cur.getString(2)); data.add(item); //將自数据库读出的数据整理到ArrayList data容器內 cur.moveToNext(); } cur.close(); ListView mListView01 = new ListView(this); SimpleAdapter adapter = new SimpleAdapter(this //设置adapter封装data数据 , data , R.layout.main , new String[] {"column00", "column01", "column02" } , new int[] {R.id.TextView01, R.id.TextView02, R.id.TextView03 }); /*将data数据的String[] {"column00", "column01", "column02" }放到显示窗体的3个TextView上*/ mListView01.setAdapter(adapter); //绑定data数据到ListView setContentView(mListView01); //将ListView放到显示窗体上显示 } }
Networks:
WebView