Создание и запрос отношений данных в Parse для Android
19 мин
отношения на android введение используя parse, вы можете хранить объекты данных, устанавливая отношения между ними для моделирования этого поведения любой \<font color="#2166ae">parseobject\</font> может использоваться как значение в других \<font color="#2166ae">parseobject\</font> внутри фреймворка parse будет храниться упоминаемый объект в одном месте, чтобы поддерживать согласованность это может дать вам дополнительную мощь при построении и выполнении сложных запросов существует три основных типа отношений \<font color="#2166ae">один к одному\</font> , устанавливающий прямые отношения между двумя объектами и только ими; \<font color="#2166ae">один ко многим\</font> , где один объект может быть связан с многими другими объектами; \<font color="#2166ae">многие ко многим\</font> , что может создать множество сложных отношений между многими объектами существует два способа создания \<font color="#2166ae">один ко многим\</font> отношения в parse первый способ — использовать \<font color="#2166ae">указатели\</font> в \<font color="#2166ae">дочернем классе,\</font> что является самым быстрым способом по времени создания и запросов второй способ — использовать \<font color="#2166ae">массивы\</font> \<font color="#2166ae">указателей\</font> в родительском классе, что может привести к медленным временам запросов в зависимости от их размера из за этой проблемы с производительностью мы будем использовать только примеры с указателями существует три способа создания \<font color="#2166ae">многие ко многим\</font> отношения в parse первый способ — использовать \<font color="#2166ae">отношения\</font> , что является самым быстрым способом по времени создания и запросов мы будем использовать это в этом руководстве второй способ — использовать \<font color="#2166ae">массивы\</font> \<font color="#2166ae">указателей\</font> что может привести к медленным временам запросов в зависимости от их размера третий способ — использовать \<font color="#2166ae">jointable\</font> где идея взята из классической базы данных когда существует отношение многие ко многим, мы объединяем каждый \<font color="#2166ae">objectid\</font> или \<font color="#2166ae">указатель\</font> с обеих сторон вместе, чтобы создать новую отдельную таблицу, в которой отслеживается связь этот учебник использует базовое приложение, созданное в android studio 4 1 1 с \<font color="#2166ae">buildtoolsversion=30 0 2\</font> , \<font color="#2166ae">compile sdk version = 30 0 2\</font> и \<font color="#2166ae">targetsdkversion 30\</font> в любое время вы можете получить доступ к полному проекту android, созданному с помощью этого учебника, в наших репозиториях на github репозиторий примера на kotlin https //github com/templates back4app/android parse sdk kotlin репозиторий примера на java https //github com/templates back4app/android parse sdk java цель наша цель понять отношения parse, создавая практическое приложение для книг вот предварительный просмотр того, что мы собираемся достичь предварительные требования чтобы завершить этот учебник, нам нужно android studio https //developer android com/studio/index html приложение, созданное на back4app примечание следуйте за учебником по созданию нового parse app https //www back4app com/docs/get started/new parse app чтобы узнать, как создать parse app на back4app android приложение, подключенное к back4app примечание следуйте за учебником по установке parse sdk https //www back4app com/docs/android/parse android sdk чтобы создать проект android studio, подключенный к back4app устройство (или виртуальное устройство https //developer android com/studio/run/managing avds html ) с android 4 1 (jelly bean) или новее понимание приложения для книг основной класс объекта, который вы будете использовать, это \<font color="#2166ae">книга\</font> , который хранит каждую запись книги в регистрации также это другие три класса объектов \<font color="#2166ae">издатель\</font> название издателя книги, \<font color="#2166ae">один ко многим\</font> отношение с \<font color="#2166ae">книга\</font> \<font color="#2166ae">жанр\</font> жанр книги, \<font color="#2166ae">один ко многим\</font> отношение с \<font color="#2166ae">книга\</font> обратите внимание, что в этом примере мы будем считать, что у книги может быть только один жанр; \<font color="#2166ae">автор\</font> автор книги, \<font color="#2166ae">многие ко многим\</font> отношение с \<font color="#2166ae">книга\</font> , так как у книги может быть более одного автора, и у автора может быть более одной книги; визуальное представление этой модели данных давайте начнем! перед следующими шагами нам нужно подключить \<font color="#2166ae">back4app\</font> к нашему приложению вам следует сохранить \<font color="#2166ae">appid\</font> и \<font color="#2166ae">clientkey\</font> из \<font color="#2166ae">back4app\</font> в файл \<font color="#2166ae">string xml\</font> и затем инициализировать \<font color="#2166ae">parse\</font> в нашем файле \<font color="#2166ae">app java\</font> или \<font color="#2166ae">app kt\</font> следуйте новому учебнику по parse app https //www back4app com/docs/android/parse android sdk если вы не знаете, как инициализировать \<font color="#2166ae">parse\</font> в вашем приложении или вы можете скачать проекты, ссылки на которые мы поделились выше, и отредактировать только \<font color="#2166ae">appid\</font> и \<font color="#2166ae">clientkey\</font> в соответствии с вашими требованиями 1 сохраните и перечислите связанные объекты книг на этом этапе мы увидим, как сохранить и перечислить \<font color="#2166ae">жанры\</font> , \<font color="#2166ae">издатели\</font> и \<font color="#2166ae">авторы\</font> классы, связанные с классом \<font color="#2166ae">книга\</font> 1 1 сохранить и перечислить жанры мы можем зарегистрировать \<font color="#2166ae">жанр\</font> с помощью следующего фрагмента 1 private void addgenre(string name) { 2 //we are taking this name parameter from the input 3 progressdialog show(); 4 parseobject parseobject = new parseobject("genre"); 5 parseobject put("name", name); 6 parseobject saveinbackground(e > { 7 progressdialog dismiss(); 8 if (e == null) { 9 getgenres(); 10 inputgenre settext(""); 11 toast maketext(this, "genre saved successfully", toast length short) show(); 12 } else { 13 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 14 } 15 }); 16 }1 private fun addgenre(name string) { 2 //we are taking this name parameter from the input 3 progressdialog show() 4 val parseobject = parseobject("genre") 5 parseobject put("name", name) 6 parseobject saveinbackground { 7 progressdialog dismiss() 8 if (it == null) { 9 getgenres() 10 inputgenre settext("") 11 toast maketext(this, "genre saved successfully", toast length short) show() 12 } else { 13 toast maketext(this, it localizedmessage, toast length short) show() 14 } 15 } 16 } мы можем зарегистрировать \<font color="#2166ae">жанр\</font> с помощью следующего фрагмента 1 private void getgenres() { 2 progressdialog show(); 3 parsequery\<parseobject> query = new parsequery<>("genre"); 4 query findinbackground((objects, e) > { 5 progressdialog dismiss(); 6 list\<parseobjectmodel> list = new arraylist<>(); 7 for (parseobject parseobject objects) { 8 list add(new parseobjectmodel(parseobject)); 9 } 10 11 genreadapter adapter = new genreadapter(list, this); 12 recyclerview\ setlayoutmanager(new linearlayoutmanager(this)); 13 recyclerview\ setadapter(adapter); 14 }); 15 }1 private fun getgenres() { 2 progressdialog show() 3 val query = parsequery\<parseobject>("genre") 4 query findinbackground { objects, e > 5 progressdialog dismiss() 6 var list mutablelist\<parseobjectmodel> = arraylist() 7 for (parseobject in objects) { 8 list add(parseobjectmodel(parseobject)) 9 } 10 val adapter = genreadapter(this, list) 11 recyclerview\ layoutmanager = linearlayoutmanager(this) 12 recyclerview\ adapter = adapter 13 } 14 } 1 2 сохранить и перечислить издателей мы можем зарегистрировать \<font color="#2166ae">издателя\</font> с помощью следующего фрагмента 1 private void addpublisher(string name) { 2 //we are taking this name parameter from the input 3 progressdialog show(); 4 parseobject parseobject = new parseobject("publisher"); 5 parseobject put("name", name); 6 parseobject saveinbackground(e > { 7 progressdialog dismiss(); 8 if (e == null) { 9 getpublishers(); 10 inputpublisher settext(""); 11 toast maketext(this, "publisher saved successfully", toast length short) show(); 12 } else { 13 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 14 } 15 }); 16 }1 private fun addpublisher(name string) { 2 //we are taking this name parameter from the input 3 progressdialog show() 4 val parseobject = parseobject("publisher") 5 parseobject put("name", name) 6 parseobject saveinbackground { 7 progressdialog dismiss() 8 if (it == null) { 9 getpublishers() 10 inputpublisher settext("") 11 toast maketext(this, "publisher saved successfully", toast length short) show() 12 } else { 13 toast maketext(this, it localizedmessage, toast length short) show() 14 } 15 } 16 } мы можем зарегистрировать \<font color="#2166ae">издателя\</font> с помощью следующего фрагмента 1 private void getpublishers() { 2 progressdialog show(); 3 parsequery\<parseobject> query = new parsequery<>("publisher"); 4 query findinbackground((objects, e) > { 5 progressdialog dismiss(); 6 list\<parseobjectmodel> list = new arraylist<>(); 7 for (parseobject parseobject objects) { 8 list add(new parseobjectmodel(parseobject)); 9 } 10 11 publisheradapter adapter = new publisheradapter(list, this); 12 recyclerview\ setlayoutmanager(new linearlayoutmanager(this)); 13 recyclerview\ setadapter(adapter); 14 }); 15 }1 private fun getpublishers() { 2 progressdialog show() 3 val query = parsequery\<parseobject>("publisher") 4 query findinbackground { objects, e > 5 progressdialog dismiss() 6 val list arraylist\<parseobjectmodel> = arraylist() 7 for (parseobject in objects) { 8 list add(parseobjectmodel(parseobject)) 9 } 10 11 val adapter = publisheradapter(this, list) 12 recyclerview\ layoutmanager = linearlayoutmanager(this) 13 recyclerview\ adapter = adapter 14 } 15 } 1 3 сохранить и перечислить авторов мы можем зарегистрировать \<font color="#2166ae">автора\</font> с помощью следующего фрагмента 1 private void addauthor(string name){ 2 //we are taking this name parameter from the input 3 progressdialog show(); 4 parseobject parseobject = new parseobject("author"); 5 parseobject put("name", name); 6 parseobject saveinbackground(e > { 7 progressdialog dismiss(); 8 if (e == null) { 9 getauthors(); 10 inputauthor settext(""); 11 toast maketext(this, "author saved successfully", toast length short) show(); 12 } else { 13 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 14 } 15 }); 16 }1 private fun addauthor(name string) { 2 //we are taking this name parameter from the input 3 progressdialog show() 4 val parseobject = parseobject("author") 5 parseobject put("name", name) 6 parseobject saveinbackground { 7 progressdialog dismiss() 8 if (it == null) { 9 getauthors() 10 inputauthor settext("") 11 toast maketext(this, "author saved successfully", toast length short) show() 12 } else { 13 toast maketext(this, it localizedmessage, toast length short) show() 14 } 15 } 16 } мы можем зарегистрировать \<font color="#2166ae">автора\</font> с помощью следующего фрагмента 1 private void getauthors() { 2 progressdialog show(); 3 parsequery\<parseobject> query = new parsequery<>("author"); 4 query findinbackground((objects, e) > { 5 progressdialog dismiss(); 6 list\<parseobjectmodel> list = new arraylist<>(); 7 for (parseobject parseobject objects) { 8 list add(new parseobjectmodel(parseobject)); 9 } 10 11 authoradapter adapter = new authoradapter(list, this); 12 recyclerview\ setlayoutmanager(new linearlayoutmanager(this)); 13 recyclerview\ setadapter(adapter); 14 }); 15 }1 private fun getauthors() { 2 progressdialog show() 3 val query = parsequery\<parseobject>("author") 4 query findinbackground { objects list\<parseobject>, e parseexception? > 5 progressdialog dismiss() 6 val list arraylist\<parseobjectmodel> = arraylist() 7 for (parseobject in objects) { 8 list add(parseobjectmodel(parseobject)) 9 } 10 val adapter = authoradapter(this, list) 11 recyclerview\ layoutmanager = linearlayoutmanager(this) 12 recyclerview\ adapter = adapter 13 } 14 } в этой части мы используем класс модели с именем \<font color="#2166ae">parseobjectmodel\</font> в этом классе модели у нас есть \<font color="#2166ae">parseobject\</font> переменная, чтобы иметь возможность читать данные, и переменная \<font color="#2166ae">ischecked\</font> , которую мы будем использовать для сохранения книги на следующем шаге мы сможем легко извлечь выбранные объекты с помощью переменной \<font color="#2166ae">ischecked\</font> вот наша \<font color="#2166ae">parseobjectmodel\</font> модель 1 public class parseobjectmodel { 2 parseobject object; 3 boolean ischecked = false; 4 5 public parseobjectmodel(parseobject object) { 6 this object = object; 7 } 8 9 public parseobject getobject() { 10 return object; 11 } 12 13 public parseobjectmodel setobject(parseobject object) { 14 this object = object; 15 return this; 16 } 17 18 public boolean ischecked() { 19 return ischecked; 20 } 21 22 public parseobjectmodel setchecked(boolean checked) { 23 ischecked = checked; 24 return this; 25 } 26 }1 class parseobjectmodel(obj parseobject) { 2 var obj parseobject? = null 3 var ischecked boolean = false 4 5 init { 6 this obj = obj 7 } 8 } 2 сохранить объект книги и его отношения 2 1 сохранить объект книги с отношением 1\ n эта функция создаст новый \<font color="#2166ae">книга\</font> в базе данных back4app с отношениями 1\ n 1 progressdialog show(); 2 book put("genre", genre); 3 book put("publisher", publisher); 4 book put("title", title); 5 book put("year", year); 6 book saveinbackground(e > { 7 progressdialog hide(); 8 if (e == null) { 9 toast maketext(addbookactivity this, "book saved successfully", toast length short) show(); 10 startactivity(new intent(addbookactivity this, booklistactivity class)); 11 finish(); 12 } else { 13 toast maketext(addbookactivity this, e getlocalizedmessage(), toast length short) show(); 14 } 15 });1 progressdialog show() 2 book put("genre", genre) 3 book put("publisher", publisher!!) 4 book put("title", title) 5 book put("year", year) 6 book saveinbackground { 7 progressdialog hide() 8 if (it == null) { 9 toast maketext(this, "book saved successfully", toast length short) show() 10 startactivity(intent(this\@addbookactivity, booklistactivity class java)) 11 finish() 12 } else { 13 toast maketext(this, it localizedmessage, toast length short) show() 14 } 15 } 2 2 сохранить объект книга с отношением n\ n эта функция создаст новый \<font color="#2166ae">книга\</font> в базе данных back4app с отношениями n\ n для \<font color="#2166ae">автор\</font> отношения мы находим выбранного автор/ов в адаптере \<font color="#2166ae">authorrecyclerview\</font> и сохраняем их как \<font color="#2166ae">parse relation\</font> 1 progressdialog show(); 2 book put("genre", genre); 3 book put("publisher", publisher); 4 book put("title", title); 5 book put("year", year); 6 7 //here we are setting book relation with getselecteditem function of bookauthoradapter 8 if (recyclerviewauthors getadapter() != null) { 9 relation = ((bookauthoradapter) recyclerviewauthors getadapter()) getselecteditems(book); 10 if (relation == null) { 11 toast maketext(this, "please select author/s", toast length short) show(); 12 return; 13 } 14 } else { 15 toast maketext(this, "something went wrong!!", toast length short) show(); 16 return; 17 } 18 19 book saveinbackground(e > { 20 progressdialog hide(); 21 if (e == null) { 22 toast maketext(addbookactivity this, "book saved successfully", toast length short) show(); 23 startactivity(new intent(addbookactivity this, booklistactivity class)); 24 finish(); 25 } else { 26 toast maketext(addbookactivity this, e getlocalizedmessage(), toast length short) show(); 27 } 28 }); 29 30 //this is the function for save author/s relation of book object this function in bookauthoradapter 31 public parserelation\<parseobject> getselecteditems(parseobject parseobject) { 32 parserelation\<parseobject> relation = parseobject getrelation("author relation"); 33 for (parseobjectmodel object this list) { 34 if (object ischecked()) 35 relation add(object getobject()); 36 } 37 return relation; 38 } 1 progressdialog show() 2 book put("genre", genre) 3 book put("publisher", publisher!!) 4 book put("title", title) 5 book put("year", year) 6 7 //here we are setting book relation with getselecteditem function of bookauthoradapter 8 9 if (recyclerviewauthors adapter != null) { 10 relation = (recyclerviewauthors adapter as bookauthoradapter) getselecteditems(book) 11 if (relation == null) { 12 toast maketext(this, "please select author/s", toast length short) show() 13 return 14 } 15 } else { 16 toast maketext(this, "something went wrong!!", toast length short) show() 17 return 18 } 19 20 book saveinbackground { 21 progressdialog hide() 22 if (it == null) { 23 toast maketext(this, "book saved successfully", toast length short) show() 24 startactivity(intent(this\@addbookactivity, booklistactivity class java)) 25 finish() 26 } else { 27 toast maketext(this, it localizedmessage, toast length short) show() 28 } 29 } 30 31 //this is the function for save author/s relation of book object this function in bookauthoradapter 32 33 fun getselecteditems(parseobject parseobject) parserelation\<parseobject>? { 34 var relation\ parserelation\<parseobject>? = parseobject getrelation("author relation") 35 for (obj in this list) { 36 if (obj ischecked) 37 relation? add(obj obj) 38 } 39 return relation 40 } 3 запросить детали книги с отношениями с помощью этих функций мы перечислим наши \<font color="#2166ae">книги\</font> в соответствии с их \<font color="#2166ae">издателями\</font> сначала мы отправим запрос к классу издатель 1 progressdialog show(); 2 parsequery\<parseobject> query = new parsequery<>("publisher"); 3 query findinbackground((objects, e) > { 4 progressdialog hide(); 5 if (e == null) { 6 booklistadapter adapter = new booklistadapter(objects, this); 7 recyclerview\ setlayoutmanager(new linearlayoutmanager(this)); 8 recyclerview\ setadapter(adapter); 9 } else { 10 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 11 } 12 });1 progressdialog show() 2 val query = parsequery\<parseobject>("publisher") 3 query findinbackground { objects list\<parseobject>?, e parseexception? > 4 progressdialog hide() 5 if (e == null) { 6 val adapter = booklistadapter(this, objects!!) 7 recyclerview\ layoutmanager = linearlayoutmanager(this) 8 recyclerview\ adapter = adapter 9 } else { 10 toast maketext(this, e localizedmessage, toast length short) show() 11 } 12 } а затем мы запрашиваем список \<font color="#2166ae">книг\</font> к которым относится каждый \<font color="#2166ae">издатель\</font> 1 parseobject object = list get(position); 2 holder title settext(object getstring("name")); 3 parsequery\<parseobject> query = new parsequery<>("book"); 4 query whereequalto("publisher", object); 5 query findinbackground((objects, e) > { 6 if (e == null) { 7 booksadapter adapter = new booksadapter(objects, context); 8 holder books setlayoutmanager(new linearlayoutmanager(context)); 9 holder books setadapter(adapter); 10 } else { 11 toast maketext(context, e getlocalizedmessage(), toast length short) show(); 12 } 13 });1 val `object` = list\[position] 2 holder title text = `object` getstring("name") 3 val query = parsequery\<parseobject>("book") 4 query whereequalto("publisher", `object`) 5 query findinbackground { objects list\<parseobject>?, e parseexception? > 6 if (e == null) { 7 val adapter = booksadapter(context, objects!!) 8 holder books layoutmanager = linearlayoutmanager(context) 9 holder books adapter = adapter 10 } else { 11 toast maketext(context, e localizedmessage, toast length short) show() 12 } 13 } теперь, когда мы нажимаем на любой \<font color="#2166ae">книгу\</font> объект, мы отправляем идентификатор объекта этой \<font color="#2166ae">книги\</font> с намерением на страницу, которая покажет детали этой \<font color="#2166ae">книги\</font> и мы получаем все детали \<font color="#2166ae">книги \</font> из базы данных, используя этот идентификатор объекта на этой странице 1 private void getbookwithdetails() { 2 progressdialog show(); 3 parsequery\<parseobject> query = new parsequery<>("book"); 4 query getinbackground(getintent() getstringextra("objectid"), (object, e) > { 5 if (e == null) { 6 booktitle settext("title " +object getstring("title")); 7 bookyear settext("year " +object getstring("year")); 8 try { 9 bookgenre settext("genre " +object getparseobject("genre") fetchifneeded() getstring("name")); 10 } catch (parseexception parseexception) { 11 parseexception printstacktrace(); 12 } 13 try { 14 bookpublisher settext("publisher " + object getparseobject("publisher") fetchifneeded() getstring("name")); 15 } catch (parseexception parseexception) { 16 parseexception printstacktrace(); 17 } 18 19 object getrelation("author relation") getquery() findinbackground((objects, e1) > { 20 progressdialog hide(); 21 if (e1 == null) { 22 bookdetailauthoradapter adapter = new bookdetailauthoradapter(objects, this); 23 authorrecyclerview\ setlayoutmanager(new linearlayoutmanager(this)); 24 authorrecyclerview\ setadapter(adapter); 25 } else { 26 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 27 } 28 }); 29 } else { 30 progressdialog hide(); 31 toast maketext(this, e getlocalizedmessage(), toast length short) show(); 32 } 33 }); 34 }1 private fun getbookwithdetails() { 2 progressdialog show() 3 val query = parsequery\<parseobject>("book") 4 5 query getinbackground(intent getstringextra("objectid")) { `object`, e > 6 if (e == null) { 7 booktitle text = "title " + `object` getstring("title") 8 bookyear text = "year " + `object` getstring("year") 9 try { 10 bookgenre text = "genre " + `object` getparseobject("genre")? fetchifneeded\<parseobject>()? getstring("name") 11 } catch (parseexception parseexception) { 12 parseexception printstacktrace() 13 } 14 try { 15 bookpublisher text = 16 "publisher " + `object` getparseobject("publisher")? fetchifneeded\<parseobject>()? getstring("name") 17 } catch (parseexception parseexception) { 18 parseexception printstacktrace() 19 } 20 21 `object` getrelation\<parseobject>("author relation") query findinbackground { objects, e1 > 22 progressdialog hide() 23 if (e1 == null) { 24 val adapter = bookdetailauthoradapter(this, objects) 25 authorrecyclerview\ layoutmanager = linearlayoutmanager(this) 26 authorrecyclerview\ adapter = adapter 27 } else { 28 toast maketext(this, e1 localizedmessage, toast length short) show() 29 } 30 } 31 } else { 32 progressdialog hide() 33 toast maketext(this, e localizedmessage, toast length short) show() 34 } 35 } 36 } сделано! на данный момент мы изучили \<font color="#2166ae">связи parse\</font> на \<font color="#2166ae">android\</font>