Android
Data objects
Парсинг и хранение типов данных на Android c Back4App
23 мин
парсинг типов данных на android введение в этом руководстве вы узнаете о типах данных parse, используя android вы будете читать и сохранять объекты parse на back4app из android приложения хранение данных в parse основано на parseobject parseobject каждый parseobject parseobject содержит пары ключ значение совместимых с json данных эти данные не имеют схемы, что означает, что нам не нужно заранее указывать, какие ключи существуют в каждом parseobject parseobject мы можем устанавливать любые пары ключ значение, которые хотим, и наш бэкенд будет их хранить например, предположим, что мы отслеживаем высокие результаты для игры один parseobject parseobject может содержать ключи должны быть алфавитно цифровыми строками, а значения могут быть строка строка => строка строка число число (примитивные числовые значения, такие как int int , double double ) булевый булевый => boolean boolean дата и время дата и время => java util date ноль ноль => jsonobject null массив массив =>jsonarray файл файл => parse file указатель указатель => другой parseobject связь связь => parserelation геоточка геоточка => parsegeopoint каждый parseobject parseobject имеет имя класса, которое мы можем использовать для различения различных типов данных например, мы могли бы назвать объект высокого счета gamescore gamescore также есть несколько полей, которые нам не нужно указывать, так как они предоставляются для удобства objectid objectid является уникальным идентификатором для каждого сохраненного объекта createdat createdat и updatedat updatedat представляют время, когда каждый объект был создан и последний раз изменен в облаке каждое из этих полей автоматически заполняется back4app в момент, когда мы сохраняем новый parseobject parseobject мы рекомендуем вам nameyourclasseslikethis nameyourclasseslikethis (uppercamelcase) и nameyourkeyslikethis nameyourkeyslikethis (lowercamelcase), просто чтобы ваш код выглядел красиво этот учебник использует базовое приложение, созданное в android studio 4 1 1 с buildtoolsversion=30 0 2 buildtoolsversion=30 0 2 , compile sdk version compile sdk version = 30 0 2 30 0 2 и targetsdkversion 30 targetsdkversion 30 в любое время вы можете получить доступ к полному проекту через наши репозитории на github репозиторий примера на kotlin репозиторий примера на java цель наша цель создать android приложение, которое может обрабатывать все типы данных, предоставляемые parse server вот предварительный просмотр того, что мы собираемся достичь предварительные требования чтобы завершить этот учебник, нам нужно android studio приложение, созданное на back4app примечание следуйте за учебником по созданию нового parse app чтобы узнать, как создать parse app на back4app android приложение, подключенное к back4app примечание следуйте за учебником по установке parse sdk чтобы создать проект android studio, подключенный к back4app устройство (или виртуальное устройство ) с android 4 1 (jelly bean) или новее понимание нашего приложения вы создадите приложение для лучшего понимания parse типы данных типы данных в этом android android приложении вы создадите все типы данных в классе с именем datatypes datatypes и присвоите значения переменным этого класса затем мы будем читать и обновлять эти данные примечание типы данных указатель указатель , связь связь , файл файл , геоточка геоточка будут рассмотрены позже в специальных руководствах давайте начнем! 1 создать шаблон приложения определите следующие переменные в mainactivity mainactivity и замените код в методе oncreate oncreate следующим кодом 1 private progressdialog progressdialog; 2 private view popupinputdialogview; 3 private recyclerview recyclerview; 4 private string objectid; 5 private static final string tag = "mainactivity"; 6 7 @override 8 protected void oncreate(bundle savedinstancestate) { 9 super oncreate(savedinstancestate); 10 setcontentview(r layout activity main); 11 12 progressdialog = new progressdialog(mainactivity this); 13 14 button savedata = findviewbyid(r id savedata); 15 button readdata = findviewbyid(r id readdata); 16 button updatedata = findviewbyid(r id updatedata); 17 18 savedata setonclicklistener(savedataview > { 19 try { 20 savedatatypes(); 21 } catch (jsonexception e) { 22 e printstacktrace(); 23 } 24 }); 25 26 readdata setonclicklistener(readdataview > readobjects()); 27 28 updatedata setonclicklistener(updatedataview > updateobject()); 29 30 }1 private var progressdialog progressdialog? = null 2 private var objectid string? = null 3 private var popupinputdialogview view? = null 4 private var recyclerview recyclerview? = null 5 private val tag = "mainactivity" 6 7 override fun oncreate(savedinstancestate bundle?) { 8 super oncreate(savedinstancestate) 9 setcontentview(r layout activity main) 10 11 progressdialog = progressdialog(this\@mainactivity) 12 val savedata = findviewbyid\<button>(r id savedata) 13 val readdata = findviewbyid\<button>(r id readdata) 14 val updatedata = findviewbyid\<button>(r id updatedata) 15 16 savedata setonclicklistener { 17 try { 18 savedatatypes() 19 } catch (e jsonexception) { 20 e printstacktrace() 21 } 22 } 23 readdata setonclicklistener { readobjects() } 24 updatedata setonclicklistener { updateobject() } 25 } перед следующими шагами нам нужно подключить back4app back4app к нашему приложению вам следует сохранить appid appid и clientkey clientkey из back4app back4app в файл string xml string xml и затем инициализировать parse parse в нашем файле app java app java или app kt app kt следуйте за новым учебником по parse app если вы не знаете, как инициализировать parse parse в вашем приложении 2 код для сохранения объекта функция create создаст новый объект в базе данных back4app мы определяем функцию savedatatypes savedatatypes которую мы вызываем в функции oncreate oncreate и используем следующий код в этой функции мы сохраним все типы данных с помощью этой функции в объект классов datatypes 1 private void savedatatypes() throws jsonexception{ 2 parseobject parseobject = new parseobject("datatypes"); 3 4 parseobject put("stringfield", "string"); 5 parseobject put("doublefield", 1 5); 6 parseobject put("intfield", 2); 7 parseobject put("boolfield", true); 8 parseobject put("datefield", calendar getinstance() gettime()); 9 10 jsonobject myobject = new jsonobject(); 11 myobject put("number", 1); 12 myobject put("string", "42"); 13 14 parseobject put("jsonobject", myobject); 15 16 17 jsonarray myarray = new jsonarray(); 18 myarray put(myobject); 19 myarray put(myobject); 20 myarray put(myobject); 21 22 parseobject put("jsonarray", myarray); 23 24 25 list\<string> list = new arraylist<>(); 26 list add("string1"); 27 list add("string2"); 28 parseobject put("liststringfield", list); 29 30 list\<integer> listint = new arraylist<>(); 31 listint add(1); 32 listint add(2); 33 listint add(3); 34 parseobject put("listintfield", listint); 35 36 list\<boolean> listbool = new arraylist<>(); 37 listbool add(true); 38 listbool add(false); 39 parseobject put("listboolfield", listbool); 40 41 progressdialog show(); 42 parseobject saveinbackground(e > { 43 progressdialog dismiss(); 44 if (e == null) { 45 toast maketext(this, "object created successfully ", toast length short) show(); 46 objectid = parseobject getobjectid(); 47 } else { 48 objectid = null; 49 toast maketext(this, e getmessage(), toast length long) show(); 50 } 51 }); 52 }1 private fun savedatatypes() { 2 val parseobject = parseobject("datatypes") 3 4 parseobject put("stringfield", "string") 5 parseobject put("doublefield", 1 5) 6 parseobject put("intfield", 2) 7 parseobject put("boolfield", true) 8 parseobject put("datefield", calendar getinstance() time) 9 10 11 val myobject = jsonobject() 12 myobject put("number", 1) 13 myobject put("string", "42") 14 15 parseobject put("jsonobject", myobject) 16 17 val myarray = jsonarray() 18 myarray put(myobject) 19 myarray put(myobject) 20 myarray put(myobject) 21 22 parseobject put("jsonarray", myarray) 23 24 val list mutablelist\<string> = arraylist() 25 list add("string1") 26 list add("string2") 27 parseobject put("liststringfield", list) 28 29 val listint mutablelist\<int> = arraylist() 30 listint add(1) 31 listint add(2) 32 listint add(3) 33 parseobject put("listintfield", listint) 34 35 val listbool mutablelist\<boolean> = arraylist() 36 listbool add(true) 37 listbool add(false) 38 parseobject put("listboolfield", listbool) 39 40 progressdialog? show() 41 parseobject saveinbackground { 42 progressdialog? dismiss() 43 if (it == null) { 44 toast maketext(this, "object created successfully ", toast length short) show() 45 objectid = parseobject objectid 46 } else { 47 objectid = null 48 toast maketext(this, it message, toast length long) show() 49 } 50 } 51 } 3 код для чтения объекта мы передадим переменную objectid objectid , которую мы назначили в функции savedatatypes savedatatypes в качестве параметра запроса и прочитаем данные, которые мы сохранили в функции savedatatypes savedatatypes с помощью функции readobjects readobjects 1 private void readobjects() { 2 if (objectid == null) { 3 toast maketext(this, "no object click on the 'save data' button before ", toast length short) show(); 4 return; 5 } 6 7 parsequery\<parseobject> query = new parsequery<>("datatypes"); 8 9 progressdialog show(); 10 query getinbackground(objectid, (object, e) > { 11 progressdialog dismiss(); 12 if (e == null) { 13 list\<data> list = new arraylist<>(); 14 list add(new data("int list field",object get("listintfield") tostring())); 15 list add(new data("string field",object get("stringfield") tostring())); 16 list add(new data("double field",object get("doublefield") tostring())); 17 list add(new data("int field",object get("intfield") tostring())); 18 list add(new data("string list field",object get("liststringfield") tostring())); 19 list add(new data("date field",object get("datefield") tostring())); 20 list add(new data("bool field",object get("boolfield") tostring())); 21 list add(new data("list bool field",object get("listboolfield") tostring())); 22 list add(new data("json object field",object get("jsonobject") tostring())); 23 list add(new data("json array field",object get("jsonarray") tostring())); 24 25 showdatatypes(list); 26 27 } else { 28 toast maketext(this, e getmessage(), toast length short) show(); 29 } 30 }); 31 }1 private fun readobjects() { 2 if (objectid == null) { 3 toast maketext( 4 this, 5 "no object click on the 'save data' button before ", 6 toast length short 7 ) show() 8 return 9 } 10 11 val query = parsequery\<parseobject>("datatypes") 12 13 14 progressdialog? show() 15 query getinbackground( 16 objectid 17 ) { obj, e > 18 progressdialog? dismiss() 19 if (e == null) { 20 21 val list mutablelist\<data> = arraylist() 22 list add(data("int list field", obj get("listintfield") tostring())) 23 list add(data("string field",obj get("stringfield") tostring())) 24 list add(data("double field", obj get("doublefield") tostring())) 25 list add(data("int field", obj get("intfield") tostring())) 26 list add(data("string list field", obj get("liststringfield") tostring())) 27 list add(data("date field",obj get("datefield") tostring())) 28 list add(data("bool field", obj get("boolfield") tostring())) 29 list add(data("list bool field", obj get("listboolfield") tostring())) 30 list add(data("json object field", obj get("jsonobject") tostring())) 31 list add(data("json array field", obj get("jsonarray") tostring())) 32 showdatatypes(list) 33 } else { 34 toast maketext(this, e message, toast length short) show() 35 } 36 37 } 38 } в этом разделе мы создали класс модели под названием data data мы используем данные, которые получаем в функции readobjects readobjects , чтобы создавать объекты из этого класса модели мы передаем эти объекты как элементы в список, который мы создали в data data типа затем мы передаем этот список в качестве параметра функции showdatatypes showdatatypes и выводим его в alertdialog alertdialog это данные данные модель 1 public class data { 2 private string type; 3 private string value; 4 5 public data(string type, string value) { 6 this type = type; 7 this value = value; 8 } 9 10 public string gettype() { 11 return type; 12 } 13 14 public data settype(string type) { 15 this type = type; 16 return this; 17 } 18 19 public string getvalue() { 20 return value; 21 } 22 23 public data setvalue(string value) { 24 this value = value; 25 return this; 26 } 27 }1 class data(val type\ string?=null,val value\ string?=null) { 2 3 } это showdatatypes showdatatypes функция 1 private void showdatatypes(list\<data> list){ 2 alertdialog builder alertdialogbuilder = new alertdialog builder(mainactivity this); 3 alertdialogbuilder settitle("data types"); 4 alertdialogbuilder setcancelable(true); 5 initpopupviewcontrols(list); 6 //we are setting our custom popup view by alertdialog builder 7 alertdialogbuilder setview(popupinputdialogview); 8 final alertdialog alertdialog = alertdialogbuilder create(); 9 alertdialog show(); 10 } 11 12 private void initpopupviewcontrols(list\<data> list) { 13 layoutinflater layoutinflater = layoutinflater from(mainactivity this); 14 popupinputdialogview = layoutinflater inflate(r layout custom alert dialog, null); 15 recyclerview = popupinputdialogview\ findviewbyid(r id recyclerview); 16 itemadapter adapter = new itemadapter(list,this); 17 recyclerview\ setlayoutmanager(new linearlayoutmanager(this,linearlayoutmanager vertical,false)); 18 recyclerview\ setadapter(adapter); 19 }1 private fun showdatatypes(list list\<data>) { 2 val alertdialogbuilder = alertdialog builder(this\@mainactivity) 3 alertdialogbuilder settitle("data types") 4 alertdialogbuilder setcancelable(true) 5 initpopupviewcontrols(list) 6 //we are setting our custom popup view by alertdialog builder 7 alertdialogbuilder setview(popupinputdialogview) 8 val alertdialog = alertdialogbuilder create() 9 alertdialog show() 10 } 11 12 @suppresslint("inflateparams") 13 private fun initpopupviewcontrols(list list\<data>) { 14 val layoutinflater = layoutinflater from(this\@mainactivity) 15 popupinputdialogview = layoutinflater inflate(r layout custom alert dialog, null) 16 recyclerview = popupinputdialogview? findviewbyid(r id recyclerview) 17 val adapter = itemadapter(this\@mainactivity, list) 18 recyclerview? layoutmanager = linearlayoutmanager( 19 this, 20 linearlayoutmanager vertical, 21 false 22 ) 23 recyclerview? adapter = adapter 24 } 4 код для обновления объекта функция updateobject updateobject отвечает за обновление данных в объекте, созданном с помощью функции savedatatypes savedatatypes мы снова используем objectid objectid для обновления объекта 1 public void updateobject() { 2 if (objectid == null) { 3 toast maketext(this, "no object click on the 'save data' button before ", toast length short) show(); 4 return; 5 } 6 7 parseobject parseobject = new parseobject("datatypes"); 8 parseobject setobjectid(objectid); 9 parseobject put("intfield", 5); 10 parseobject put("stringfield", "new string"); 11 12 progressdialog show(); 13 14 parseobject saveinbackground(e > { 15 progressdialog dismiss(); 16 if (e == null) { 17 toast maketext(this, "object updated successfully ", toast length short) show(); 18 } else { 19 toast maketext(this, e getmessage(), toast length short) show(); 20 } 21 }); 22 }1 private fun updateobject() { 2 if (objectid == null) { 3 toast maketext( 4 this, 5 "no object click on the 'save data' button before ", 6 toast length short 7 ) show() 8 return 9 } 10 11 val parseobject = parseobject("datatypes") 12 parseobject objectid = objectid 13 parseobject put("intfield", 5) 14 parseobject put("stringfield", "new string") 15 16 progressdialog? show() 17 18 parseobject saveinbackground { 19 progressdialog? dismiss() 20 if (it == null) { 21 toast maketext(this, "object updated successfully ", toast length short) show() 22 } else { 23 toast maketext(this, it message, toast length short) show() 24 } 25 } 26 } 5 использование счетчиков приведённый выше пример содержит общий случай использования поле intfield intfield может быть счетчиком, который нам нужно будет обновлять постоянно приведённое выше решение работает, но оно громоздкое и может привести к проблемам, если у нас есть несколько клиентов, пытающихся обновить один и тот же счетчик parse предоставляет методы, которые атомарно увеличивают любое числовое поле, чтобы помочь с хранением данных типа счетчика таким образом, то же самое обновление можно переписать как 1 parseobject parseobject = new parseobject("datatypes"); 2 parseobject setobjectid(objectid); 3 parseobject increment("intfield",1);1 val parseobject = parseobject("datatypes") 2 parseobject objectid = objectid 3 parseobject increment("intfield",1) 6 использование списков parse также предоставляет методы для помощи в хранении данных списков существует три операции, которые можно использовать для атомарного изменения поля списка setadd setadd и setaddall setaddall добавляет заданные объекты в конец поля массива setaddunique setaddunique и setaddallunique setaddallunique добавляет только заданные объекты, которые еще не содержатся в поле массива, в это поле позиция вставки не гарантируется remove remove и removeall removeall удаляет все экземпляры заданных объектов из поля массива 6 1 примеры с add и addall liststringfield liststringfield имеет значение запуск кода ниже 1 parseobject parseobject = new parseobject("datatypes"); 2 parseobject setobjectid(objectid); 3 parseobject add("liststringfield","e"); 4 parseobject addall("liststringfield", arrays aslist("e", "f", "g", "g")); 5 parseobject save();1 val parseobject = parseobject("datatypes") 2 parseobject objectid = objectid 3 parseobject add("liststringfield", "e") 4 parseobject addall("liststringfield", arrays aslist("e", "f", "g", "g")) 5 parseobject save() после этой команды результат поля stringlist будет 6 2 примеры с addunique и addallunique liststringfield liststringfield имеет значение запуск кода ниже 1 parseobject parseobject = new parseobject("datatypes"); 2 parseobject setobjectid(objectid); 3 parseobject addunique("liststringfield","e"); 4 parseobject addallunique("liststringfield",arrays aslist("c", "d", "e", "f")); 5 parseobject save();1 val parseobject = parseobject("datatypes") 2 parseobject objectid = objectid 3 parseobject addunique("liststringfield", "e") 4 parseobject addallunique("liststringfield", arrays aslist("c", "d", "e", "f")) 5 parseobject save() после этой команды результат поля stringlist stringlist будет значения не повторялись 6 3 примеры с removeall liststringfield liststringfield имеет значение запуск кода ниже 1 parseobject parseobject = new parseobject("datatypes"); 2 parseobject setobjectid(objectid); 3 parseobject removeall("liststringfield",arrays aslist("c", "d", "e", "f")); 4 parseobject save();1 val parseobject = parseobject("datatypes") 2 parseobject objectid = objectid 3 parseobject removeall("liststringfield", arrays aslist("c", "d", "e", "f")) 4 parseobject save() после этой команды результат поля stringlist stringlist будет примечание что в настоящее время невозможно атомарно добавлять и удалять элементы из массива в одном сохранении нам придется вызывать сохранение для каждой отдельной операции с массивом 7 удалить одно поле из parseobject вы можете удалить одно поле из объекта, используя remove remove операцию 1 parseobject parseobject = new parseobject("datatypes"); 2 parseobject remove("stringfield"); 3 parseobject save();1 val parseobject = parseobject("datatypes") 2 parseobject remove("stringfield") 3 parseobject save() готово! на данный момент мы узнали о типах данных parse типах данных parse на android android