{"id":327454,"date":"2022-01-10T08:54:00","date_gmt":"2022-01-10T08:54:00","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=327454"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=327454","title":{"rendered":"<span>\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Flutter \u0432 production. \u0421\u043e\u0437\u0434\u0430\u0435\u043c IT-\u0432\u0435\u0440\u0444\u0438<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\" class=\"article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/6-\/yh\/bn\/6-yhbncdpelvfswcscqzzzkhxp8.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/6-\/yh\/bn\/6-yhbncdpelvfswcscqzzzkhxp8.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<h1 id=\"pro-nas\">\u041f\u0440\u043e \u043d\u0430\u0441<\/h1>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u044b <a href=\"https:\/\/habr.com\/ru\/users\/levitckii-daniil\/\">\u0414\u0430\u043d\u0438\u0438\u043b \u041b\u0435\u0432\u0438\u0446\u043a\u0438\u0439 <\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/users\/wardrone\/\">\u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0414\u0440\u043e\u043d\u043e\u0432<\/a>, \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 <a href=\"https:\/\/ati.su\">ATI.SU<\/a> \u2014 \u043a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0435\u0439 \u0432 \u0420\u043e\u0441\u0441\u0438\u0438 \u0438 \u0421\u041d\u0413 \u0411\u0438\u0440\u0436\u0435 \u0433\u0440\u0443\u0437\u043e\u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043e\u043a. \u0425\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c \u0432\u0438\u0434\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Flutter. <\/p>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0438 \u0440\u0430\u043d\u044c\u0448\u0435 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u043c\u0438\u0440 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 Flutter. \u0423 \u043d\u0430\u0441, \u043a\u0430\u043a \u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0431\u044b\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u043f\u044b\u0442 \u0432 \u044d\u0442\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041d\u043e \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u0440\u0443\u043f\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0441 \u043f\u0440\u0438\u0446\u0435\u043b\u043e\u043c \u043d\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0442\u0430\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0435 \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0420\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u044b \u0441\u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u043b\u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d-\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u043e\u0432\u044b\u0445 Flutter-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p><a href=\"https:\/\/github.com\/atidev\/ATI.SU-Flutter-Template-Project\">FLUTTER-\u0428\u0410\u0411\u041b\u041e\u041d-\u041f\u0420\u0418\u041c\u0415\u0420<\/a><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0430 \u043d\u0435\u043f\u043e\u043a\u043e\u043b\u0435\u0431\u0438\u043c\u0443\u044e \u0438\u0441\u0442\u0438\u043d\u0443, \u0438 \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044b \u043a \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0434\u0438\u0441\u043a\u0443\u0441\u0441\u0438\u0438. \u041d\u043e \u043e\u043d\u0438 \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0442 \u043d\u0430\u0448 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u043e\u043f\u044b\u0442 \u0438 \u043d\u0430\u0431\u0438\u0442\u044b\u0435 \u0448\u0438\u0448\u043a\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0438\u0441\u044c \u0441\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u0445 \u0441\u0440\u0430\u0437\u0443. \u041d\u043e, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430\u0448 \u0448\u0430\u0431\u043b\u043e\u043d \u043d\u0430 GitHub \u0438\u043b\u0438 \u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. \u041d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u0437 Flutter-\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 \u043d\u0430\u0448 \u043e\u043f\u044b\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d.<\/p>\n<p>  <\/p>\n<h1 id=\"arhitektura-proekta\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/dd\/n5\/h5\/ddn5h51fhfzrme6fkn4tzuk5zas.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/dd\/n5\/h5\/ddn5h51fhfzrme6fkn4tzuk5zas.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"1-struktura-proekta\">1. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>  <\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0443\u044e \u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u043a, \u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438. \u041d\u0435\u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0440\u0435\u0447\u0438\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438. <\/p>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0432\u0438\u0434\u0430:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" data-src=\"https:\/\/habrastorage.org\/webt\/8n\/dq\/lh\/8ndqlha5fmelybhigu115votoeg.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 1. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p><em>app<\/em> \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a Application Flutter-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u043a \u0442\u0435\u043c\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 app\" data-src=\"https:\/\/habrastorage.org\/webt\/rr\/q7\/hl\/rrq7hlrercdinr3e9gsy7qkxxnu.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 2. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 app<\/em><\/p>\n<p>  <\/p>\n<p><em>arch<\/em> \u2014 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\/\u0443\u0442\u0438\u043b\u0438\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0435 pub-\u043f\u0430\u043a\u0435\u0442\u044b, \u043d\u043e \u043e\u043d\u0438 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u0442\u0430\u043a\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 BLoC, \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 arch\" data-src=\"https:\/\/habrastorage.org\/webt\/kf\/t8\/cl\/kft8cly9jdhksku14tayrpd2nhu.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 3. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 arch<\/em><\/p>\n<p>  <\/p>\n<p><em>const<\/em> \u2014 \u043e\u0431\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 4. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 const\" data-src=\"https:\/\/habrastorage.org\/webt\/hn\/z6\/ca\/hnz6canqp8srfll2gn3wvp8tgzg.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 4. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 const<\/em><\/p>\n<p>  <\/p>\n<p><em>core<\/em> \u2014 \u044f\u0434\u0440\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u0444\u0438\u0447\u0430\u043c, \u0431\u0435\u0437 \u043d\u0435\u0433\u043e \u043e\u043d\u0438 \u043d\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u043e\u0431\u0449\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0442\u044c\u044e \u0438\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u043e\u0431\u0449\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 5. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 core\" data-src=\"https:\/\/habrastorage.org\/webt\/67\/no\/b8\/67nob8kzhqaabbzhrc9t3wr5jd0.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 5. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 core<\/em><\/p>\n<p>  <\/p>\n<p><em>features<\/em> \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0444\u0438\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0424\u0438\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u0431\u0438\u0437\u043d\u0435\u0441-\u0441\u043b\u043e\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0444\u0438\u0447\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u0434\u0432\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 package: api package \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0444\u0438\u0447\u0438; impl package \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u0441\u0435 \u0444\u0438\u0447\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 core-api packge \u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 feature-api package. <\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 6. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 features\" data-src=\"https:\/\/habrastorage.org\/webt\/2e\/b-\/zq\/2eb-zqtgfrbwhctmbmv-57o9c_a.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 6. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 features<\/em><\/p>\n<p>  <\/p>\n<h2 id=\"2-biznes-sloi\">2. \u0411\u0438\u0437\u043d\u0435\u0441-\u0441\u043b\u043e\u0438<\/h2>\n<p>  <\/p>\n<p>\u0414\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435\u0441\u044c \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435: \u043a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u0436\u0438\u0432\u0443\u044e \u00ab\u043f\u043e\u0449\u0443\u043f\u0430\u0439\u0442\u0435\u00bb \u0432\u0441\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0435\u043c\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043d\u0438\u0437\u043a\u0430\u044f \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430 (\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0449\u0435 \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f);<\/li>\n<li>\u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0437\u043e\u043d \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430;<\/li>\n<li>\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0441\u0442\u044c \u0438 \u043d\u0438\u0437\u043a\u0438\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430;<\/li>\n<li>\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c (\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Clean Architecture \u043f\u043e\u0434\u0445\u043e\u0434.\u00a0\u042d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043d\u0430\u00a0\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u043b\u043e\u0438, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043b\u043e\u044f \u0441\u0432\u043e\u044f \u0437\u043e\u043d\u0430 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438. <\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043d\u044f\u0442\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043b\u043e\u0438: <strong>Presentation, Domain, Data.<\/strong> \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e clean-\u043f\u043e\u0434\u0445\u043e\u0434 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 <strong><a href=\"https:\/\/habr.com\/ru\/company\/mobileup\/blog\/335382\/\">\u0417\u0430\u0431\u043b\u0443\u0436\u0434\u0435\u043d\u0438\u044f Clean Architecture<\/a><\/strong> \u0438\u043b\u0438 \u0432 <a href=\"https:\/\/developer.android.com\/jetpack\/guide\">**\u0433\u0430\u0439\u0434\u0435 \u043e\u0442 Google<\/a>.** <\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u0443\u0435\u043c, \u043a\u0430\u043a \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043b\u043e\u0438 \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 Flutter-\u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>  <\/p>\n<h3 id=\"presentation\"><strong>Presentation<\/strong><\/h3>\n<p>  <\/p>\n<p>\u0421\u043b\u043e\u0439, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c. \u0414\u0430\u043d\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li><strong>UI-\u043e\u0431\u044a\u0435\u043a\u0442\u044b<\/strong> \u2014 \u043d\u0430\u0431\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443. \u0421\u044e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043d\u0435\u0441\u0442\u0438 Page-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, Widget-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u043e \u0441\u0442\u0438\u043b\u044f\u043c\u0438, \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439, \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. UI-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0437 Presentation-\u0441\u043b\u043e\u044f.<\/li>\n<li><strong>State Managment \u043e\u0431\u044a\u0435\u043a\u0442\u044b<\/strong> \u2014 \u043d\u0430\u0431\u043e\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0445 \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 UI-\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0442\u0430\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c: Presenter, ViewModel, BLoC \u0438 \u0442.\u0434. \u0412 \u043d\u0430\u0448\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f BLoC. \u0422\u0430\u043a\u0436\u0435 \u0435\u0449\u0451 \u043e\u0434\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u2014 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. State Managment-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u044e\u0442 \u043e\u0431 UI-\u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0437 Domain \u0441\u043b\u043e\u044f \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 State Managment-\u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 7. \u041f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 presentation \u0441\u043b\u043e\u044f\" data-src=\"https:\/\/habrastorage.org\/webt\/co\/se\/xq\/cosexqsw39iztoxv0oshyc9dcvu.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 7. \u041f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 presentation \u0441\u043b\u043e\u044f<\/em><\/p>\n<p>  <\/p>\n<h3 id=\"domain\"><strong>Domain<\/strong><\/h3>\n<p>  <\/p>\n<p>\u0421\u043b\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043e\u0442 UI \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0411\u0438\u0437\u043d\u0435\u0441-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u043e\u044e, \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043a\u0443\u0441\u043e\u043a \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u044f \u0432 package \u0438\u0437 Flutter-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 Dart-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0431\u0435\u0437 Flutter-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0441 \u0431\u0435\u043a\u0435\u043d\u0434\u043e\u043c (<a href=\"https:\/\/pub.dev\/packages\/shelf\">Shelf<\/a>-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c) \u0438\u043b\u0438 CLI.<\/p>\n<p>  <\/p>\n<p>Interactor \u2014 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u043e\u0435. \u041e\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0438\u043b\u0438 \u043d\u0430\u0431\u043e\u0440\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432. <\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0433\u043b\u0430\u0441\u043d\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d Interactor, \u043d\u043e \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0440\u044f\u0434\u0430 \u043e\u0431\u0449\u0438\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432 \u043e\u0434\u0438\u043d Intreactor. <\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u043f\u043e\u043c\u0438\u043c\u043e Interactor \u043d\u0430 \u044d\u0442\u043e\u043c \u0441\u043b\u043e\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 Builder-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, CommandProcessor-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u044f \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0437 Data \u0441\u043b\u043e\u044f \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438\u0437 Domain \u0441\u043b\u043e\u044f.<\/p>\n<p>  <\/p>\n<h3 id=\"data\"><strong>Data<\/strong><\/h3>\n<p>  <\/p>\n<p>\u0421\u043b\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u041a \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u043e\u044e \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0442\u0440\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<ul>\n<li><strong>\u041f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong> \u2014 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u0441\u0435\u0442\u044c\u044e. \u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0438\u043c\u0435\u043d\u0443\u0435\u043c \u0438\u0445 Service-\u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0442\u0438\u043f\u0430\u043c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430: ApiService, DbService, CacheService \u0438 \u043f\u0440\u043e\u0447\u0438\u0435. \u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0432\u043e\u0435\u0433\u043e \u0442\u0438\u043f\u0430, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f DTO-\u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u043b\u0438 Request\/Response-\u043c\u043e\u0434\u0435\u043b\u0438.<\/li>\n<li><strong>Repository-\u043e\u0431\u044a\u0435\u043a\u0442\u044b<\/strong> \u2014 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437\u043e\u043b\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442 \u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f. \u041d\u0430\u0440\u0443\u0436\u0443(\u0432 Domain \u0441\u043b\u043e\u0439) Repository-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u0438\u0437\u043d\u0435\u0441-\u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u041c\u044b \u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c Repository-\u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 (\u043d\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c Stream, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u044d\u0442\u0438\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438, \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438).<\/li>\n<li><strong>\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b<\/strong> \u2014 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 Repository\/Service \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2014 mapper-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 DTO-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0432 \u0431\u0438\u0437\u043d\u0435\u0441-\u043c\u043e\u0434\u0435\u043b\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 8. \u041f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 data \u0441\u043b\u043e\u044f.\" data-src=\"https:\/\/habrastorage.org\/webt\/f5\/lt\/mo\/f5ltmoduhlpfkgeubwxxqx_i_0c.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 8. \u041f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 data \u0441\u043b\u043e\u044f<\/em><\/p>\n<p>  <\/p>\n<h2 id=\"3-state-managment\">3. State Managment<\/h2>\n<p>  <\/p>\n<p>\u0412 Flutter-\u0441\u0440\u0435\u0434\u0435 \u0435\u0441\u0442\u044c \u0440\u044f\u0434 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 State Managment \u0440\u0435\u0448\u0435\u043d\u0438\u0439: <a href=\"https:\/\/pub.dev\/packages\/bloc\">bloc<\/a>, MVVM-\u0440\u0435\u0448\u0435\u043d\u0438\u044f (<a href=\"https:\/\/pub.dev\/packages\/stacked\">stacked<\/a>, <a href=\"https:\/\/pub.dev\/packages\/elementary\">elementary<\/a>), <a href=\"https:\/\/pub.dev\/packages\/redux\">redux<\/a>, <a href=\"https:\/\/pub.dev\/packages\/mobx\">mobx<\/a>. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u0438\u0445 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0445 \u043c\u043e\u0436\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0432 <a href=\"https:\/\/docs.flutter.dev\/development\/data-and-backend\/state-mgmt\/options\">\u043f\u043e\u0434\u0431\u043e\u0440\u043a\u0435 \u043d\u0430 flutter.dev<\/a>. <\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 Android-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0431\u043b\u0438\u0437\u043a\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0431\u044b\u043b <a href=\"https:\/\/hannesdorfmann.com\/android\/mosby3-mvi-1\/\">MVI<\/a> (\u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 <a href=\"https:\/\/www.youtube.com\/watch?v=hBkQkjWnAjg\">\u0434\u043e\u043a\u043b\u0430\u0434 \u043e\u0442 \u0421\u0435\u0440\u0433\u0435\u044f \u0420\u044f\u0431\u043e\u0432\u0430<\/a>), \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 BLoC c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f Flutter \u2014 <a href=\"https:\/\/pub.dev\/packages\/flutter_bloc\">flutter_bloc<\/a>. BLoC-\u043f\u043e\u0434\u0445\u043e\u0434 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0437\u0443\u044e\u0442 \u0447\u0435\u0442\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f Event \u0432 State,\u00a0\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u0434\u0438\u0432\u0438\u043b\u0430 \u043e\u0431\u0448\u0438\u0440\u043d\u0430\u044f <a href=\"https:\/\/bloclibrary.dev\/#\/gettingstarted\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f BLoC<\/a>. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" alt=\"\u0420\u0438\u0441\u0443\u043d\u043e\u043a 9. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 BLoC-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\" data-src=\"https:\/\/habrastorage.org\/webt\/ml\/rj\/jy\/mlrjjyukmlf9prntdxady6hn--y.png\"\/><br \/>  <em>\u0420\u0438\u0441\u0443\u043d\u043e\u043a 9. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 BLoC-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b<\/em><\/p>\n<p>  <\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 MVI \u043f\u043e\u043c\u0438\u043c\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 State \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u043f\u043e\u0442\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 SingleResult (Effect\/SingleLiveEvent). \u0418\u0445 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0435 \u0432\u043b\u0438\u044f\u044e\u0442 \u0434\u0440\u0443\u0433 \u043d\u0430 \u0434\u0440\u0443\u0433\u0430, \u0438 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 UI \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e, \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u043d\u0430 \u043f\u043e\u0442\u043e\u043a SingleResult \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c SingleResult. \u041d\u0430\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0431\u044b\u043b \u0431\u044b \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0434\u043b\u044f BLoC, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438, \u043f\u043e\u043a\u0430\u0437\u0430 Snackbar\/Toast, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u0430\u043c\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439. <\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 SrBloc:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">abstract class SrBloc&lt;Event, State, SR> extends Bloc&lt;Event, State> with SingleResultMixin&lt;Event, State, SR> {   SrBloc(State state) : super(state); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 SingleResultMixin SrBloc \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u0432\u0430 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 [SingleResult] abstract class SingleResultProvider&lt;SingleResult> {   Stream&lt;SingleResult> get singleResults; }  \/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u043f\u0440\u0438\u0435\u043c\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 [SingleResult] abstract class SingleResultEmmiter&lt;SingleResult> {   void addSr(SingleResult sr); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e BLoC \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Generic \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 SingleResult, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class MainPageBloc extends SrBloc&lt;MainPageEvent, MainPageState, MainPageSR>  @freezed class MainPageSR with _$MainPageSR {   const factory MainPageSR.showSnackbar({required String text}) = _ShowSnackbar; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 Event \u0432\u043d\u0443\u0442\u0440\u0438 BLoC \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 Widget-\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u0442 SingleResult \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 addSr. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u043e\u043a\u0430\u0437 Snackbar \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">FutureOr&lt;void> _chekTime(MainPageEventCheckTime event, Emitter&lt;MainPageState> emit) async {     final timeResult = await greatestTimeInteractor.getGreatestServerOrPhoneTime();      if (timeResult.isRight) {       emit(state.data.copyWith(timeText: timeResult.right.toString()));     } else {       addSr(MainPageSR.showSnackbar(text: LocaleKeys.time_unknown.tr()));     }   }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 SingleResult \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Page-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0444\u0438\u0447\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class MainPage extends StatelessWidget {     ...     void _onSingleResult(BuildContext context, MainPageSR sr) {     sr.when(       showSnackbar: (text) => BaseSnackbar.show(context: context, text: text),     );   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SrBloc \u043c\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b\u0438 \u0442\u0430\u043a\u0436\u0435 \u0438 BlocBuilder \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u2014 SrBlocBuilder. \u041e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 \u043d\u0430 singleResults:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">typedef SingleResultListener&lt;SR> = void Function(BuildContext context, SR singleResult);  \/\/\/ \u0412\u0438\u0434\u0436\u0435\u0442-\u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 bloc-builder \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 SrBloc class SrBlocBuilder&lt;B extends SrBloc&lt;Object?, S, SR>, S, SR> extends StatelessWidget {   final B? bloc;   final SingleResultListener&lt;SR> onSR;   final BlocWidgetBuilder&lt;S> builder;   final BlocBuilderCondition&lt;S>? buildWhen;      ...    @override   Widget build(BuildContext context) {     return StreamListener&lt;SR>(       stream: (bloc ?? context.read&lt;B>()).singleResults,       onData: (data) => onSR(context, data),       child: BlocBuilder(         bloc: bloc,         builder: builder,         buildWhen: buildWhen,       ),     );   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 SrBloc \u0432 Widget-\u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445 \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0432\u0438\u0434\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class MainPage extends StatelessWidget {     ...   @override   Widget build(BuildContext context) {     return BlocProvider&lt;MainPageBloc>(       create: (_) => GetIt.I.get()..add(const MainPageEvent.init()),       child: SrBlocBuilder&lt;MainPageBloc, MainPageState, MainPageSR>(         onSR: _onSingleResult,         builder: (_, blocState) {           return Scaffold(             body: SafeArea(               child: blocState.map(                 empty: (state) => const _MainPageEmpty(),                 data: (state) => _MainPageContent(state: state),               ),             ),           );         },       ),     );   }     ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u043e\u043d \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043d\u0435 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 BLoC, \u0438 \u0432\u0438\u0434\u0436\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class _MainPageContent extends StatelessWidget {   @override   Widget build(BuildContext context) {     final appTheme = AppTheme.of(context);     final bloc = context.read&lt;MainPageBloc>();      return Center(       child: Column(         mainAxisSize: MainAxisSize.min,         children: [           Text(             state.descriptionText,             style: appTheme.textTheme.body1Medium,           ),           const SizedBox(height: 8),           if (state.timeText.isNotEmpty) Text(state.timeText),           ElevatedButton(             onPressed: () {               bloc.add(const MainPageEvent.checkTime());             },             child: Text(state.timeButtonText),           ),           ElevatedButton(             onPressed: () {               bloc.add(const MainPageEvent.unauthorize());             },             child: Text(state.logoutButtonText),           ),         ],       ),     );   } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"4-klassy-modeli\">4. \u041a\u043b\u0430\u0441\u0441\u044b-\u043c\u043e\u0434\u0435\u043b\u0438<\/h2>\n<p>  <\/p>\n<p>\u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u043b\u0430\u0441\u0441\u043e\u0432-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e Data-\u043a\u043b\u0430\u0441\u0441\u0430\u043c \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 Kotlin). \u0422\u0430\u043a \u043a\u0430\u043a \u0432 Dart \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <strong><a href=\"https:\/\/pub.dev\/packages\/freezed\">freezed<\/a><\/strong>, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043d\u0430 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/pub.dev\/packages\/build_runner\">build_runner<\/a>).<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ DTO \u043a\u043b\u0430\u0441\u0441, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 @freezed class TimeResponse with _$TimeResponse {   const factory TimeResponse({     @JsonKey(name: 'currentDateTime') required DateTime currentDateTime,     @JsonKey(name: 'serviceResponse') required Map&lt;String, dynamic>? serviceResponse,   }) = _TimeResponse;    factory TimeResponse.fromJson(Map&lt;String, dynamic> json) => _$TimeResponseFromJson(json); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438-\u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438, \u043f\u043e\u043c\u0438\u043c\u043e \u0441\u0430\u043c\u0438\u0445 data-\u043a\u043b\u0430\u0441\u0441\u043e\u0432 (\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432, toString, equals, copyWith \u043c\u0435\u0442\u043e\u0434\u043e\u0432) \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Sealed\/Union \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438, \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 <a href=\"https:\/\/pub.dev\/packages\/json_serializable\">json_serializable<\/a>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u0435\u0435 <a href=\"https:\/\/github.com\/google\/json_serializable.dart\/tree\/master\/json_serializable\">\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f<\/a> \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043e\u043d\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">@freezed class LoginSR with _$LoginSR {   const factory LoginSR.success() = _Success;    const factory LoginSR.showSnackbar({required String text}) = _ShowSnackbar; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 freezed \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c <em>.freezed.dart, <\/em>.g.dart \u0444\u0430\u0439\u043b\u044b \u0432 \u0432\u0430\u0448\u0435\u0439 IDE. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f VsCode \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">{     ...     \"files.exclude\": {         \"**\/*.freezed.dart\": true,         \"**\/*.g.dart\": true     } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"vnedrenie-zavisimostey\">\u0412\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h2>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" data-src=\"https:\/\/habrastorage.org\/webt\/ir\/no\/mr\/irnomre2kjznn_h_4f0hq17xy04.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0432\u044f\u0437\u043a\u0443 <a href=\"https:\/\/pub.dev\/packages\/get_it\">GetIt<\/a> \u0438 <a href=\"https:\/\/pub.dev\/packages\/injectable\">Injectable<\/a>.<\/p>\n<p>  <\/p>\n<p><strong>GetIt<\/strong> \u2014 \u0441\u0435\u0440\u0432\u0438\u0441-\u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043d\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c. GetIt \u043a\u0440\u0430\u0439\u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0439, \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0443 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (singleton, lazySingleton, fabric, async*), \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e Scope-\u0430\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 Environment.<\/p>\n<p>  <\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e Scopes<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Scope \u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c dispose \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043d\u043e \u043c\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043b\u043e\u0442\u043d\u043e \u0441 \u043d\u0438\u043c\u0438 \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0441 \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 package. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u0437\u0430\u0434\u0435\u043b \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<p>  <\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>Injectable<\/strong> \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043d\u0430\u0434 GetIt, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 GetIt \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 (@Injectable, <a href=\"https:\/\/habr.com\/ru\/users\/singleton\/\" class=\"user_link\">Singleton<\/a> \u0438 \u0442 \u0434). \u0412 \u0438\u0442\u043e\u0433\u0435 <a href=\"https:\/\/pub.dev\/packages\/injectable_generator\">\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440<\/a> \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 \u0441\u0442\u0430\u0434\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/pub.dev\/packages\/build_runner\">build_runner<\/a>) \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u0432\u00a0GetIt:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">... \/\/ ignore_for_file: lines_longer_than_80_chars \/\/\/ initializes the registration of provided dependencies inside of [GetIt] Future&lt;_i1.GetIt> $initGetIt(_i1.GetIt get,     {String? environment, _i2.EnvironmentFilter? environmentFilter}) async {   final gh = _i2.GetItHelper(get, environment, environmentFilter);   final infrastructureModule = _$InfrastructureModule();   final dbModule = _$DbModule();   final routerModule = _$RouterModule();   final dioClientModule = _$DioClientModule();   gh.singleton&lt;_i3.AppThemeBloc>(_i3.AppThemeBloc());   gh.singleton&lt;_i4.Connectivity>(infrastructureModule.connectivity);   gh.lazySingleton&lt;_i5.DioLoggerWrapper>(       () => infrastructureModule.dioLoggerWrapper(get&lt;_i6.AppEnvironment>()));   gh.singleton&lt;_i7.KeyValueStore>(_i8.SharedPrefsKeyValueStore());   gh.singleton&lt;_i9.LinkProvider>(_i9.LinkProvider());   gh.lazySingleton&lt;_i10.Logger>(       () => infrastructureModule.logger(get&lt;_i6.AppEnvironment>())); ...<\/code><\/pre>\n<p>  <\/p>\n<p>Injectable \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b GetIt, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u043e\u043b\u043e\u0441\u0441\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u044b\u043c.<\/p>\n<p>  <\/p>\n<h1 id=\"dizayn-sistema\">\u0414\u0438\u0437\u0430\u0439\u043d-\u0441\u0438\u0441\u0442\u0435\u043c\u0430<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" data-src=\"https:\/\/habrastorage.org\/webt\/qk\/39\/gi\/qk39giy3yit8-l9tkp3ekrqlvps.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u0435\u0440\u0434\u0446\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u0435\u0433\u043e \u0441\u0442\u0438\u043b\u044c \u0438 \u0434\u0438\u0437\u0430\u0439\u043d, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0441\u044a\u0435\u0434\u0430\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 UI \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043e\u0432 \u0438\u0437 \u0441\u0442\u0430\u0434\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u044d\u0442\u0430\u043f\u043e\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u044f\u0437\u044b\u043a \u0441 \u0432\u0430\u0448\u0438\u043c\u0438 UI\/UX-\u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u0430\u043c\u0438. \u041f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u044d\u0442\u043e\u043c \u043e\u0431\u0449\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 <a href=\"https:\/\/paradigm.mail.ru\/design_tokens\">\u0434\u0438\u0437\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u043e\u0432<\/a>, \u043f\u0440\u043e\u043d\u0438\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0432\u0441\u0435 \u043c\u0430\u043a\u0435\u0442\u044b \u0438 \u0432\u0441\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0442\u0435\u043a\u0430\u0442\u044c \u0432\u0430\u0448\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0432\u0430\u0448\u0443 \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0431\u0443\u0434\u0443\u0442 \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043f\u0430\u043b\u0438\u0442\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f;<\/li>\n<li>\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0446\u0432\u0435\u0442\u043e\u0432\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u2014 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u0438\u0437\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0446\u0432\u0435\u0442\u043e\u0432 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u0430\u043b\u0438\u0442\u0440\u044b \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0442\u0435\u043c\u0435 (\u0441\u0432\u0435\u0442\u043b\u043e\u0439\/\u0442\u0435\u043c\u043d\u043e\u0439\/\u043a\u043e\u043d\u0442\u0440\u0430\u0441\u0442\u043d\u043e\u0439);<\/li>\n<li>\u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u2014 \u0441\u0432\u044f\u0437\u044c \u0434\u0438\u0437\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0448\u0440\u0438\u0444\u0442\u0430 (\u0440\u0430\u0437\u043c\u0435\u0440, \u0442\u043e\u043b\u0449\u0438\u043d\u0430, \u043c\u0435\u0436\u0431\u0443\u043a\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0438 \u0442.\u0434.).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044d\u0442\u0443 \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432\u044b \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u0435 \u0432 \u043a\u043e\u0434\u0435, \u0432 Flutter \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0431\u0432\u044f\u0437\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043c\u0430\u043c\u0438 ThemeData + ColorScheme + TextTheme. \u041e\u0434\u043d\u0430\u043a\u043e, \u0434\u0438\u0437\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u044b Flutter \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0434\u0438\u0437\u0430\u0439\u043d \u0432\u0438\u0434\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438. \u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0451\u043d\u043d\u043e\u0441\u0442\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0410\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0446\u0432\u0435\u0442\u043e\u0432\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 abstract class AppColorTheme {   \/\/============================== Main Colors ==============================   Brightness get brightness;    Color get accent;    Color get accentVariant;    Color get onAccent;    Color get secondaryAccent;    Color get secondaryAccentVariant;    Color get onSecondary;    \/\/============================== Typography Colors ==============================   Color get textPrimary;    Color get textSecondary;     ... }  \/\/\/ \u0426\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u043f\u0430\u043b\u0438\u0442\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f class AppPallete {   static const Color blackA100 = Color(0xFF000000);   static const Color blackA85 = Color(0xD9000000);   ...   static const Color red500 = Color(0xFFF44336);   static const Color green500 = Color(0xFF4CAF50);   static const Color yellow500 = Color(0xFFFFEB3B); }  \/\/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0432\u0435\u0442\u043b\u043e\u0439 \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0442\u0435\u043c\u044b, \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0446\u0432\u0435\u0442\u043e\u0432\u044b\u0435 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0430\u043b\u0438\u0442\u0440\u043e\u0439 class LightColorTheme implements AppColorTheme {   @override   Brightness get brightness => Brightness.light;    \/\/============================== Customization color tokens ==============================   @override   Color get accent => AppPallete.lightBlu500;   @override   Color get accentVariant => AppPallete.lightBlue900;   @override   Color get onAccent => AppPallete.white;    @override   Color get secondaryAccent => accent;   @override   Color get secondaryAccentVariant => accentVariant; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0435\u0434\u0438\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 InheritedWidget AppThemeProvider:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0449\u0435\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u0435\u043c\u044b \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 @freezed class AppTheme with _$AppTheme {   \/\/\/ [colorTheme] - \u0446\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0442\u0435\u043c\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438   \/\/\/ [textTheme] - \u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0442\u0435\u043c\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438   const factory AppTheme({     required AppColorTheme colorTheme,     required AppTextTheme textTheme,   }) = _AppTheme;    static AppTheme of(BuildContext context) => AppThemeProvider.of(context).theme; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f singleton BLoC-\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \/\/\/ \/\/\/ \u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f singleton \u0432 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441, \/\/\/ \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0430\u043a\u0442\u0430\u0443\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u043e \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f @singleton class AppThemeBloc extends Bloc&lt;AppThemeEvent, AppTheme> {   AppThemeBloc()       : super(AppTheme(           colorTheme: const LightColorTheme(),           textTheme: BaseTextTheme(),         )) {     on&lt;AppThemeEventSetDarkTheme>(_setDarkTheme);     on&lt;AppThemeEventSetLightTheme>(_setLightTheme);   }     ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0442\u0435\u043c\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 UI:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">Widget build(BuildContext context) {     final appTheme = AppTheme.of(context);     final bloc = context.read&lt;MainPageBloc>();      return Center(       child: Column(         mainAxisSize: MainAxisSize.min,         children: [           Text(             state.descriptionText,             style: appTheme.textTheme.body1Medium,           ),           const SizedBox(height: 8),           if (state.timeText.isNotEmpty) Text(state.timeText),           ElevatedButton(             onPressed: () {               bloc.add(const MainPageEvent.checkTime());             },             child: Text(state.timeButtonText),           ),           ElevatedButton(             onPressed: () {               bloc.add(const MainPageEvent.unauthorize());             },             child: Text(state.logoutButtonText),           ),         ],       ),     );   }<\/code><\/pre>\n<p>  <\/p>\n<h1 id=\"rabota-s-setyu\">\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0441\u0435\u0442\u044c\u044e<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/k6\/_g\/l3\/k6_gl3mlfi72f91vamq6idymoqq.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/k6\/_g\/l3\/k6_gl3mlfi72f91vamq6idymoqq.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"1-http-klient\">1. HTTP-\u043a\u043b\u0438\u0435\u043d\u0442<\/h2>\n<p>  <\/p>\n<p>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u0430\u044f \u0444\u0438\u0447\u0430 \u043d\u0435 \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0431\u0435\u0437 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0442\u044c\u044e, \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d REST. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 REST \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 HTTP-\u043a\u043b\u0438\u0435\u043d\u0442 <a href=\"https:\/\/pub.dev\/packages\/dio\">Dio<\/a>. \u041e\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438: \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 cookies \u0438 headers, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 proxy, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 content-type \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043e\u043c\u0435\u043d\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0432\u043e\u0439 DIO-\u043a\u043b\u0438\u0435\u043d\u0442 \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/habr.com\/ru\/users\/named\/\" class=\"user_link\">Named<\/a> \u043a\u043b\u044e\u0447\u0435\u0439 GetIt: <\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 [Dio] @module abstract class DioClientModule {   @Named(InjectableNames.timeHttpClient)   @preResolve   @singleton   Future&lt;Dio> makeDioClient(DioClientCreator dioClientCreator) => dioClientCreator.makeTimeDioClient();    @lazySingleton   DioErrorHandler&lt;DefaultApiError> makeDioErrorHandler(Logger logger) => DioErrorHandlerImpl&lt;DefaultApiError>(         connectivity: Connectivity(),         logger: logger,         parseJsonApiError: (json) async {           \/\/\u043c\u0435\u0442\u043e\u0434, \u043f\u0430\u0440\u0441\u044f\u0449\u0438\u0439 \u043e\u0448\u0438\u0431\u043a\u0443 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430           return (json != null) ? DefaultApiError.fromJson(json) : null;         },       ); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 DioClientCreator:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">@Singleton(as: DioClientCreator) class DioClientCreatorImpl implements DioClientCreator {   static const defaultConnectTimeout = 5000;   static const defaultReceiveTimeout = 25000;    @protected   final LinkProvider linkProvider;   @protected   final AppEnvironment appEnvironment;   @protected   final DioLoggerWrapper logger;     ...    @override   Future&lt;Dio> makeTimeDioClient() => _baseDio(linkProvider.timeHost);    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Dio   Future&lt;Dio> _baseDio(final String url) async {     final startDio = Dio();      startDio.options.baseUrl = url;     startDio.options.connectTimeout = defaultConnectTimeout;     startDio.options.receiveTimeout = defaultReceiveTimeout;      if (appEnvironment.enableDioLogs) {       startDio.interceptors.add(         PrettyDioLogger(           requestBody: true,           logPrint: logger.logPrint,         ),       );     }      startDio.transformer = FlutterTransformer();     return startDio;   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 http-\u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 ApiSerivce-\u043e\u0431\u044a\u0435\u043a\u0442, \u0438\u0437\u043e\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 http-\u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0448\u0438\u0431\u043e\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">@Singleton(as: TimeApiService) class TimeApiServiceImpl implements TimeApiService {   static const _nowTimeApi = '\/api\/json\/utc\/now';    final Dio _client;   final DioErrorHandler&lt;DefaultApiError> _dioErrorHandler;    TimeApiServiceImpl(     @Named(InjectableNames.timeHttpClient) this._client,     this._dioErrorHandler,   );    @override   Future&lt;Either&lt;CommonResponseError&lt;DefaultApiError>, TimeResponse>> getTime() async {     final result = await _dioErrorHandler.processRequest(() => _client.get&lt;Map&lt;String, dynamic>>(_nowTimeApi));     if (result.isLeft) return Either.left(result.left);     return Either.right(TimeResponse.fromJson(result.right.data!));   } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"2-obrabotka-oshibok\">2. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043e\u043a \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/hackage.haskell.org\/package\/category-extras-0.52.0\/docs\/Control-Monad-Either.html\">\u043c\u043e\u043d\u0430\u0434\u0443 Either<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f: Left \u0438\u043b\u0438 Right. \u041e\u0431\u044b\u0447\u043d\u043e Left \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0430 Right \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Either \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0421\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0434\u0442\u0438 \u0434\u0432\u0443\u043c\u044f \u043f\u0443\u0442\u044f\u043c\u0438 [L] \u0438\u043b\u0438 [R] \/\/\/ \u041a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a, \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u043b\u0435\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u0430 \u043f\u0440\u0430\u0432\u0430\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 @freezed class Either&lt;L, R> with _$Either&lt;L, R> {   bool get isLeft => this is _EitherLeft&lt;L, R>;    bool get isRight => this is _EitherRight&lt;L, R>;    \/\/\/ \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u0435\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u0430 [Either], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \"\u041e\u0448\u0438\u0431\u043a\u043e\u0439\"   L get left => (this as _EitherLeft&lt;L, R>).left;    \/\/\/ \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0430\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u0430 [Either], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \"\u0423\u0441\u043f\u0435\u0445\u043e\u043c\"   R get right => (this as _EitherRight&lt;L, R>).right;    const Either._();    const factory Either.left(L left) = _EitherLeft;    const factory Either.right(R right) = _EitherRight; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043c\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u044c CommonResponseError, Custom \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f Generic, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0439 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0443\u044e \u0438\u0437 json-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0442\u0435\u043b\u0435 http-\u043e\u0448\u0438\u0431\u043a\u0438:  <\/p>\n<pre><code class=\"dart\">class CommonResponseError&lt;Custom> with _$CommonResponseError {     ...    \/\/\/ \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442   const factory CommonResponseError.noNetwork() = _NoNetwork;    \/\/\/ \u0421\u0435\u0440\u0432\u0435\u0440 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043c\u0435\u0442\u043e\u0434\u0443   const factory CommonResponseError.unAuthorized() = _UnAuthorized;    \/\/\/ \u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0440\u043d\u0443\u043b \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0443\u044e, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432   const factory CommonResponseError.tooManyRequests() = _TooManyRequests;    \/\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 [CustomError]   const factory CommonResponseError.customError(Custom customError) = _CustomError;    \/\/\/ \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430   const factory CommonResponseError.undefinedError(Object? errorObject) = _UndefinedError; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c DioErrorHandler:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 [MakeRequest] \u043e\u0442 [Dio] \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 [Either] \/\/\/ \u041b\u0435\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0438\u0434\u0430 [CommonResponseError] \/\/\/ \u041f\u0440\u0430\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 Dio [Response] abstract class DioErrorHandler&lt;DE> {   Future&lt;Either&lt;CommonResponseError&lt;DE>, T>> processRequest&lt;T>(MakeRequest&lt;T> makeRequest); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f retry-\u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f json \u0432 CustomError \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u044b\u0431\u043e\u0440 \u0432\u0435\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">Future&lt;CommonResponseError&lt;DE>> _processDioError(DioError e) async {     final responseData = e.response?.data;     final statusCode = e.response?.statusCode;      if (e.type == DioErrorType.connectTimeout ||         e.type == DioErrorType.sendTimeout ||         statusCode == _HttpStatus.networkConnectTimeoutError) {       return const CommonResponseError.noNetwork();     }      if (statusCode == _HttpStatus.unauthorized) {       return const CommonResponseError.unAuthorized();     }      if (statusCode == _HttpStatus.tooManyRequests) {       return const CommonResponseError.tooManyRequests();     }      if (undefinedErrorCodes.contains(statusCode)) {       return CommonResponseError.undefinedError(e);     }      Object? errorJson;     if (responseData is String) {       \/\/\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u0441\u044f Response&lt;String> dio \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043d\u0443\u044e json-\u043e\u0448\u0438\u0431\u043a\u0443       \/\/\u0438 \u043d\u0430\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e       try {         errorJson = jsonDecode(responseData);       } on FormatException {         \/\/\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b \u043d\u0430\u0440\u0443\u0448\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\/\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0441\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u0431\u0435\u0434\u0430, \u0442\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u0435\u0440\u043d\u0435\u043c [CommonResponseError.undefinedError]         logger.w('\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043e\u0442\u0432\u0435\u0442: \\n \"$responseData\" \\n \u0447\u0442\u043e \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f JSON');       }     } else if (responseData is Map&lt;String, dynamic>) {       \/\/\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0436\u0438\u0434\u0430\u043b JSON, \u0442\u043e \u0438 json-\u043e\u0442\u0432\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u0432\u0438\u0434\u0443       errorJson = responseData;     }      if (errorJson is Map&lt;String, dynamic>) {       try {         final apiError = await parseJsonApiError(errorJson);         if (apiError != null) {           return CommonResponseError.customError(apiError);         }         \/\/ ignore: avoid_catching_errors       } on TypeError catch (e) {         logger.w('\u041e\u0442\u0432\u0435\u0442 c \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \\n $responseData \\n \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0443 ApiError', e);       }     }      return CommonResponseError.undefinedError(e);   }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">@freezed class DefaultApiError with _$DefaultApiError {   const factory DefaultApiError({     required String name,     required String code,   }) = _DefaultApiError;    factory DefaultApiError.fromJson(Map&lt;String, dynamic> json) => _$DefaultApiErrorFromJson(json); }  @lazySingleton   DioErrorHandler&lt;DefaultApiError> makeDioErrorHandler(Logger logger) => DioErrorHandlerImpl&lt;DefaultApiError>(         connectivity: Connectivity(),         logger: logger,         parseJsonApiError: (json) async {           \/\/\u043c\u0435\u0442\u043e\u0434, \u043f\u0430\u0440\u0441\u044f\u0449\u0438\u0439 \u043e\u0448\u0438\u0431\u043a\u0443 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430           return (json != null) ? DefaultApiError.fromJson(json) : null;         },       );<\/code><\/pre>\n<p>  <\/p>\n<h1 id=\"navigaciya\">\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" data-src=\"https:\/\/habrastorage.org\/webt\/lm\/-v\/ta\/lm-vtalb29srobzp_hzeg56x3-q.png\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"1-yadro-navigacii\">1. \u042f\u0434\u0440\u043e \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438<\/h2>\n<p>  <\/p>\n<p>Fltuter \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u0434\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438: <strong>Navigator API<\/strong> (\u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c) \u0438 <strong>Router API<\/strong> (\u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c).<\/p>\n<p>  <\/p>\n<p><strong>Router<\/strong>, \u043d\u0430 \u043d\u0430\u0448 \u0432\u0437\u0433\u043b\u044f\u0434, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0438 \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0422\u0430\u043a\u0436\u0435 \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Web-URI. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 API-\u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439 \u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c: <strong><a href=\"https:\/\/habr.com\/ru\/company\/rshb\/blog\/584348\/\">Flutter: \u043a\u0430\u043a \u043c\u044b \u0432\u044b\u0431\u0438\u0440\u0430\u043b\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f?<\/a><\/strong><\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e Router, \u0442\u043e \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043c\u0438\u043d\u0443\u0441\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c API, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0435\u0434\u0451\u0442 \u043a \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043d\u0438\u043c. \u041c\u044b \u043f\u043e\u0448\u043b\u0438 \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u00ab\u043c\u043e\u043d\u0441\u0442\u0440\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438\u00bb \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f\u043c\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043e\u043d \u043f\u043b\u043e\u0442\u043d\u043e \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u043b\u0441\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0435\u0448\u0438\u043b\u0438 \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0435\u0433\u043e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0441 pub.dev. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 <a href=\"https:\/\/pub.dev\/packages\/auto_route\">auto_route<\/a>.<\/p>\n<p>  <\/p>\n<p><strong>auto_route<\/strong> \u2014 \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 Flutter. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c deepLinks \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c, \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0430\u043b\u043e \u043a\u043e\u0434\u0430, \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439 \u0438 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p>  <\/p>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 app_router.dart. \u0418\u043c\u0435\u043d\u043d\u043e \u0432 \u043d\u0435\u043c \u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0440\u043e\u0443\u0442-\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0442\u0443\u0442 \u0436\u0435 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u043c \u0440\u043e\u0443\u0442-\u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0420\u043e\u0443\u0442\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f @AdaptiveAutoRouter(   replaceInRouteName: 'Page,Route',   routes: &lt;AutoRoute>[     AutoRoute(page: SplashPage),     AutoRoute(       path: '\/main',       page: MainPage,       initial: true,       guards: [AuthGuard, InitGuard],     ),     AutoRoute(       path: '\/login',       page: LoginPage,       guards: [InitGuard],     ),     AutoRoute(       path: '*',       page: NotFoundPage,       guards: [InitGuard],     ),   ], ) class $AppRouter {}<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0431\u0438\u043b\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u043b\u0430\u0441\u0441 AppRouter, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0432\u0441\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 (\u0431\u0443\u0434\u0443\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441\u043f\u0438\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u043e\u0432 \u0438 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 \u043f\u043e \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e). \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439\u00a0AppRouter \u0431\u0443\u0434\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u0432\u0441\u0435\u0439 \u043d\u0430\u0448\u0435\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043c\u043e\u0434\u0443\u043b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041c\u043e\u0434\u0443\u043b\u044c, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 @module abstract class RouterModule {   @singleton   AppRouter appRouter(     AuthGuard authGuard,     InitGuard initGuard,   ) {     return AppRouter(       authGuard: authGuard,       initGuard: initGuard,     );   }    @singleton   AuthGuard authGuard(UserRepository userRepository) => AuthGuard(isAuthorized: userRepository.isAuthorized);    @singleton   InitGuard initGuard(StartupRepository startupRepository) => InitGuard(isInited: startupRepository.isInited);    @injectable   RouterLoggingObserver routerLoggingObserver(     Logger logger,     AppRouter appRouter,   ) {     return RouterLoggingObserver(       logger: logger,       appRouter: appRouter,     );   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448 MaterialApp:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">final appRouter = GetIt.I.get&lt;AppRouter>();      return MaterialApp.router(       ...       routeInformationParser: appRouter.defaultRouteParser(),       routerDelegate: AutoRouterDelegate(         appRouter,         navigatorObservers: () => [           GetIt.I.get&lt;RouterLoggingObserver>(),         ],       ),     );<\/code><\/pre>\n<p>  <\/p>\n<p>RouterLoggingObserver \u2014 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 AutoRouterObserver.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 AutoRouter \u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">AutoRouter.of(context).replace(const MainRoute()); AutoRouter.of(context).push(const LoginRoute());<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043d\u0430\u0441 \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u0432 AppRouter.\u00a0 <\/p>\n<p>  <\/p>\n<h2 id=\"2-zaschita-route\">2. \u0417\u0430\u0449\u0438\u0442\u0430 Route<\/h2>\n<p>  <\/p>\n<p>\u0412\u0430\u043c \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0434\u043e\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0438\u043b\u0438 \u043d\u0435 \u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u044d\u043a\u0440\u0430\u043d \u0431\u0435\u0437 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f. \u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0440\u0430\u0436\u0435\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 (routing guards). \u042d\u0442\u043e \u043d\u0435\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0441\u0442\u043e\u0438\u0442\u0441\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0438 \u00ab\u043f\u0440\u0438\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u00bb.\u00a0 \u0412 \u044d\u0442\u0438\u0445 \u0441\u0442\u0440\u0430\u0436\u0430\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0432\u043b\u0438\u044f\u044e\u0449\u0438\u0435 \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043c\u0435\u043d\u043d\u043e \u0447\u0435\u0440\u0435\u0437 AuthGuard \u043c\u044b \u0434\u043e\u0431\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u043c\u043e\u0436\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d, \u043c\u044b \u043d\u0430\u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0432\u0438\u0433\u0438\u0440\u0443\u0435\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u043b\u043e\u0433\u0438\u043d\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">typedef IsAuthorized = bool Function();  class AuthGuard extends AutoRedirectGuard {   @protected   final IsAuthorized isAuthorized;       ...    @override   void onNavigation(NavigationResolver resolver, StackRouter router) {     if (!isAuthorized()) {       router.push(LoginRoute(onAuthSuccess: () => resolver.next()));     } else {       resolver.next();     }   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0449\u0451 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0442\u043e\u043c\u0443, \u0447\u0442\u043e AuthGuard \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 AutoRedirectGuard, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0441\u0447\u0451\u0442 \u0440\u043e\u0443\u0442\u043e\u0432 \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class StartupInteractorImpl implements StartupInteractor {   ...    void _listenGlobalBroadcasts() {     _compositeSubscription.add(       userRepository.authStream().listen((_) => authGuard.reevaluate()),     );   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043b\u0438\u0448\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u0430\u043a\u0435\u0442\u0430 auto_route. \u0412 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438, \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u0442\u0430\u0431\u0430\u043c \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 <a href=\"https:\/\/github.com\/Milad-Akarie\/auto_route_library\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439<\/a>.<\/p>\n<p>  <\/p>\n<h1 id=\"hranenie-dannyh\">\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/az\/zs\/on\/azzsonrotrybpf4s8aqmz3bqxzy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/az\/zs\/on\/azzsonrotrybpf4s8aqmz3bqxzy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043e\u0444\u0444\u043b\u0430\u0439\u043d-\u0440\u0435\u0436\u0438\u043c\u0435 \u0438 \u043d\u0435 \u043c\u043e\u0433 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435. <\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u044f\u0442\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0445: <strong><a href=\"https:\/\/pub.dev\/packages\/hive\">hive<\/a><\/strong>, <strong><a href=\"https:\/\/pub.dev\/packages\/objectbox\">ObjectBox<\/a>, <a href=\"https:\/\/pub.dev\/packages\/sqflite\">sqflite<\/a>, <a href=\"https:\/\/pub.dev\/packages\/moor\">Moor<\/a><\/strong> (\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d \u0432 <strong><a href=\"https:\/\/pub.dev\/packages\/drift\">drift<\/a><\/strong>) \u0438 <strong><a href=\"https:\/\/pub.dev\/packages\/shared_preferences\">shared_preferences<\/a>.<\/strong> <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448\u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f: <\/p>\n<p>  <\/p>\n<ul>\n<li>\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u043c\u043e\u0433\u043e \u0432 \u0442\u044b\u0441\u044f\u0447\u0430\u0445;<\/li>\n<li>\u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 (\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: where, join, limit, offset);<\/li>\n<li>\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0411\u0414 \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u0438\u0437\u043e\u043b\u044f\u0442\u043e\u0432 (\u0438\u0437 foreground \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 background jobs, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c).<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"1-hranilische-nestrukturirovannyh-dannyh\">1. \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 hive. \u0415\u0433\u043e \u043f\u043b\u044e\u0441\u044b: \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043a\u0440\u0430\u0439\u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0418\u0437 \u043c\u0438\u043d\u0443\u0441\u043e\u0432 \u2014 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 query, \u0447\u0442\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u043b\u043e \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u0434\u043d\u0430\u043a\u043e, Hive \u0432\u0441\u0435 \u0435\u0449\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 KeyValue-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043d\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0442\u043e\u043a\u0435\u043d\u044b, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435), \u0447\u0435\u043c \u043c\u044b \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c. \u0421\u043f\u0443\u0441\u0442\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u043c\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0438, \u0447\u0442\u043e hive \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 (\u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 background task\/service \u0438 \u0438\u0437 foreground \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f). \u042d\u0442\u043e \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u043b\u043e \u0432\u0430\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u043d\u0430\u0441 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 KeyValue-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441\u0442\u0430\u043b\u0438 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c shared_preferences. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0441 hive \u043d\u0430 shared_prefs \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0431\u0435\u0437\u0431\u043e\u043b\u0435\u0437\u043d\u0435\u043d\u043d\u044b\u043c, \u043f\u043b\u044e\u0441, \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430\u0448\u0438 \u043c\u0438\u043d\u0438-\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u00ab\u0441\u043e\u043a\u0440\u044b\u0442\u0438\u044f\u00bb\u200e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 key-value \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0430 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u0441 [TypeStoreKey] abstract class KeyValueStore {   \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439, \u0447\u0442\u043e \u043f\u043e \u043a\u043b\u044e\u0447\u0443 [typedStoreKey], \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0435-\u043b\u0438\u0431\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   Future&lt;bool> contains(TypeStoreKey typedStoreKey);    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430   Future&lt;void> init();    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u043b\u044e\u0447\u0443 [typedStoreKey], \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0432\u0443\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f null   \/\/\/ \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0435\u0433\u043e \u0442\u0438\u043f \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a [T]   Future&lt;T?> read&lt;T>(TypeStoreKey&lt;T> typedStoreKey);    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u043b\u044e\u0447\u0443 [typedStoreKey], \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c null   Future&lt;void> write&lt;T>(TypeStoreKey&lt;T> typedStoreKey, T? value); }  \/\/\/ \u041e\u0431\u044c\u0435\u043a\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 key-value \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u0445 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c\u0438 \/\/\/ [T] - \u0442\u0438\u043f \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \/\/\/ [key] - \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 \/\/\/ \/\/\/ \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044e [T], \u043e\u0431\u044b\u0447\u043d\u043e \u043e\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438: [int], [double], [String], [bool]. class TypeStoreKey&lt;T> {   final type = T;    final String key;   TypeStoreKey(     this.key,   );    @override   String toString() => 'TypeStoreKey(key: $key)'; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f shared_prefs \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0434 [KeyValueStore] \u0434\u043b\u044f [SharedPreferences] \/\/\/ \/\/\/ \u041f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c [init] @Singleton(as: KeyValueStore) class SharedPrefsKeyValueStore implements KeyValueStore {   late SharedPreferences _sharedPreferences;    @override   Future&lt;void> init() async {     _sharedPreferences = await SharedPreferences.getInstance();   }    @override   Future&lt;T?> read&lt;T>(TypeStoreKey&lt;T> typedStoreKey) async => _sharedPreferences.get(typedStoreKey.key) as T?;    @override   Future&lt;bool> contains(TypeStoreKey typedStoreKey) async => _sharedPreferences.containsKey(typedStoreKey.key);    @override   Future&lt;void> write&lt;T>(TypeStoreKey&lt;T> typedStoreKey, T? value) async {     if (value == null) {       await _sharedPreferences.remove(typedStoreKey.key);        return;     }     switch (T) {       case int:         await _sharedPreferences.setInt(typedStoreKey.key, value as int);         break;       case String:         await _sharedPreferences.setString(typedStoreKey.key, value as String);         break;       case double:         await _sharedPreferences.setDouble(typedStoreKey.key, value as double);         break;       case bool:         await _sharedPreferences.setBool(typedStoreKey.key, value as bool);         break;       case List:         await _sharedPreferences.setStringList(typedStoreKey.key, value as List&lt;String>);         break;     }   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u043a\u043e\u0434\u0435 \u0432\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043a\u043b\u044e\u0447\u0438 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b KeyValueStore. \u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0433\u043e \u0432\u0435\u0440\u0441\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class StoreKeys {   static final prefsVersionKey = TypeStoreKey&lt;int>('prefs_version_key'); }  Future&lt;int?> _readCurrentVersion() => keyValueStore.read(prefsVersionKey);  Future&lt;void> _writeNewVersion(int newVersion) => keyValueStore.write(prefsVersionKey, newVersion);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f KeyValue-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439, \u043d\u043e \u043d\u0430\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0430\u0441\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0437 \u0447\u0435\u0433\u043e \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u043e\u0431\u0449\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0431\u0430\u0437\u0435 KeyValueStore \u2014 KeyValueStoreMigrator. \u041b\u043e\u0433\u0438\u043a\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043f\u0440\u0438 \u043f\u043e\u0434\u043d\u044f\u0442\u0438\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e schemeVersion \u0438\u0437\u043e\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430\u0445, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0445 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 [KeyValueStore] \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e [schemeVersion] abstract class KeyValueStoreMigrationLogic {   int get schemeVersion;    Future&lt;void> migrate(); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u0438\u0433\u0440\u0430\u0442\u043e\u0440\u0443 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 <em>Set migrations \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/em>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041c\u0435\u0442\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f key-value store   Future&lt;void> onCreate(int createdVersion) async {     await onCreateFunc?.call(createdVersion);     await observer?.onCreate(createdVersion);   }    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 [fromVersion] \u043d\u0430 [toVersion]   \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0431\u043e\u0440 [_migrations]   Future&lt;void> onUpgrade(int fromVersion, int toVersion) async {     var prefsVersion = fromVersion;     while (prefsVersion &lt; toVersion) {       prefsVersion++;       final migartionLogic = migrations.firstWhereOrNull((migrator) => migrator.schemeVersion == prefsVersion);       if (migartionLogic == null) {         await observer?.onMissedMigration(prefsVersion);         continue;       } else {         await migartionLogic.migrate();       }     }      await observer?.onUpgrade(fromVersion, toVersion);   }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b MigrationObserver:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u041e\u0431\u043e\u0437\u0440\u0435\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u0445 \u043c\u0438\u0433\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 abstract class MigrationObserver {   Future&lt;void> onCreate(int createdVersion);   Future&lt;void> onMissedMigration(int version);   Future&lt;void> onUpgrade(int fromVersion, int toVersion); }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"2-osnovnoe-hranilische-dannyh\">2. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <a href=\"https:\/\/pub.dev\/packages\/drift\">drift<\/a>. \u041e\u043d \u043d\u0430\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b. Drift \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0439 sqlite, \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u043e. Drift \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 build_runner, \u0437\u0430 \u0441\u0447\u0451\u0442 \u0447\u0435\u0433\u043e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u0435\u0442. \u0415\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 Dao-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439. Drift \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b <em>RAGMA journal_mode=WAL<\/em> \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0411\u0414<\/p>\n<p>  <\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 ObjectBox?<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0442\u0430\u0440\u0442\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 ObjectBox \u0435\u0449\u0435 \u043d\u0435 \u0432\u044b\u0448\u0435\u043b \u0432 \u0440\u0435\u043b\u0438\u0437, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u0435\u0433\u043e, \u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0433\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f (\u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 Android \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 ObjectBox), \u044d\u0442\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438 \u0435\u0441\u043b\u0438 ObjectBox \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0441\u0435\u0431\u044f \u043b\u0443\u0447\u0448\u0435 \u0447\u0435\u043c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u043d\u0430\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0442\u043e \u043c\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043b \u0448\u0430\u0431\u043b\u043e\u043d.<\/p>\n<p>  <\/li>\n<\/ul>\n<p>  <\/p>\n<p>Drift \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u043d\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0412\u0430\u0441 \u043f\u0440\u0438 \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u044b \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043f\u043e \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0441 \u043f\u0443\u0442\u0438, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u043f\u044b\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 KeyValueStoreMigrator, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 DriftMigrator:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">class AppDatabase extends _$AppDatabase {   @protected   final DriftMigrator&lt;AppDatabase> migrator;    @override   MigrationStrategy get migration => migrator.delegateStrategy(this);     ... }  \/\/\/ \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043d\u0430\u0434 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 Drift abstract class DriftMigrationLogic&lt;Db> {   \/\/\/ \u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043c\u0438\u0433\u0440\u0438\u0440\u0443\u0435\u043c   int get schemeVersion;    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 Moor \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e [schemeVersion]   Future&lt;void> migrate(Db database, Migrator m); }  \/\/\/ \u0421\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u044f\u044e\u0449\u0430\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 Drift class DriftMigrator&lt;Db> {     \/\/\/ \u041d\u0430\u0431\u043e\u0440 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 Drift   @protected   final Set&lt;DriftMigrationLogic&lt;Db>> migrationLogics;     ...     \/\/\/ \u041b\u0438\u0441\u0442\u0435\u043d\u0435\u0440 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439, \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438   @protected   final MigrationObserver? observer;     ...     \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u044e\u0449\u0438\u0439 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u043c\u0443\u044e [DriftMigrator] \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438   MigrationStrategy delegateStrategy(Db db) => MigrationStrategy(         onCreate: (m) => onCreate(m, db),         onUpgrade: (m, from, to) => onUpgrade(m, from, to, db),         beforeOpen: beforeOpen,       );     ...     \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0411\u0414   Future&lt;void> onCreate(Migrator m, Db db) async {     await onCreateFunc(m);     await observer?.onCreate(schemaVersion);   }    \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0411\u0414 \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 from \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e to   \/\/\/ \u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u0432\u044b\u0437\u044b\u0432\u0430\u044f \u043c\u0435\u0442\u043e\u0434 [_migrate]   Future&lt;void> onUpgrade(Migrator m, int from, int to, Db db) async {     var version = from;     while (version &lt; to) {       version++;       await _migrate(db, version, m);     }     await observer?.onUpgrade(from, to);   }      \/\/\/ \u041c\u0435\u0442\u043e\u0434 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 [database]   Future&lt;int?> _migrate(Db database, int schemaVersion, Migrator m) async {     final migrationLogic = migrationLogics.firstWhereOrNull((migrator) => migrator.schemeVersion == schemaVersion);      if (migrationLogic == null) {       await observer?.onMissedMigration(schemaVersion);     } else {       \/\/\u0415\u0441\u043b\u0438 \u043d\u0430\u0448\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u0443 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u0438 \u043e\u043d\u0430 \u043f\u0440\u0430\u0432\u0434\u0430  \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u0445\u0435\u043c\u044b       \/\/ (\u0442\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u0432\u043e\u0439\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438, \u043a\u0430\u043a \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043a\u043b\u044e\u0447\u0430 \u043c\u0430\u043f\u044b, \u0442\u0430\u043a \u0438 \u0438\u0437 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b)       await migrationLogic.migrate(database, m);     }   } <\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u043d\u0430\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0411\u0414 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435, \u0437\u0430 \u0441\u0447\u0451\u0442 \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u0441\u0442\u0430\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043b\u043e \u043b\u0435\u0433\u0447\u0435. <\/p>\n<p>  <\/p>\n<h1 id=\"okruzhenie-zapuska-prilozheniya\">\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/v9\/ju\/r-\/v9jur-wsa1kyd-agfdgvmu5qrae.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/v9\/ju\/r-\/v9jur-wsa1kyd-agfdgvmu5qrae.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0441 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u043b\u043e\u0433\u0430\u043c\u0438 \u0438\u043b\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0449\u0438\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0440\u0443\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f @freezed class AppEnvironment with _$AppEnvironment {   \/\/\/ [buildType] - \u0432\u0438\u0434 \u0431\u0438\u043b\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   \/\/\/ [debugOptions] - \u043d\u0430\u0431\u043e\u0440 debug-flutter \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   \/\/\/ [debugPaintOptions] - \u043d\u0430\u0431\u043e\u0440 debug \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 Flutter \u0434\u0432\u0438\u0436\u043a\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b   \/\/\/ [logLevel] - \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   \/\/\/ [enableEasyLocalizationLogs] - \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043b\u043e\u0433\u043e\u0432 \u0441\u043b\u043e\u044f \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438   \/\/\/ [enableBlocLogs] - \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043b\u043e\u0433\u043e\u0432 BLoC \u0441\u043b\u043e\u044f   \/\/\/ [enableRoutingLogs] - \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043b\u043e\u0433\u043e\u0432 Routing \u0441\u043b\u043e\u044f   \/\/\/ [enableDioLogs] - \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c\/\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043b\u043e\u0433\u043e\u0432 http \u0441\u043b\u043e\u044f   const factory AppEnvironment({     required BuildType buildType,     required DebugOptions debugOptions,     required DebugPaintOptions debugPaintOptions,     required AppLogLevel logLevel,     required bool enableEasyLocalizationLogs,     required bool enableBlocLogs,     required bool enableRoutingLogs,     required bool enableDioLogs,   }) = _AppEnvironment;    factory AppEnvironment.fromJson(Map&lt;String, dynamic> json) => _$AppEnvironmentFromJson(json); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 main-\u043c\u0435\u0442\u043e\u0434\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u0437\u0430\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <strong>\u2014dartdefine<\/strong>, ****\u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 AppEnvironment. \u041d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 Runner \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">\/\/\/ \u0422\u043e\u0447\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f void main() {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435\/\u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430   \/\/ \u0417\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0438\u0434\u043e\u0432 \u0441\u0431\u043e\u0440\u043e\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   const logLevelEnv = String.fromEnvironment('logLevel');   const debugInstrumentsEnv = bool.fromEnvironment('debugInstruments');    const buildType = !kReleaseMode || debugInstrumentsEnv ? BuildType.debug : BuildType.release;   final appLogLevel = AppLogLevels.getFromString(logLevelEnv);   final enableLogs = appLogLevel != AppLogLevel.nothing;    Runner.run(     AppEnvironment(       buildType: buildType,       debugOptions: DebugOptions(         debugShowCheckedModeBanner: buildType == BuildType.debug,       ),       debugPaintOptions: const DebugPaintOptions(),       logLevel: appLogLevel ?? AppLogLevel.verbose,       enableBlocLogs: enableLogs,       enableRoutingLogs: enableLogs,       enableDioLogs: enableLogs,       enableEasyLocalizationLogs: false,     ),   ); }<\/code><\/pre>\n<p>  <\/p>\n<p>AppEnvironment \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a singleton \u0432 DI-\u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043b\u044e\u0431\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 <strong>&#8212;dart_define<\/strong> \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u00a0 \u0418\u043d\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u043c\u043e\u0433 \u043d\u0430\u043c \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0442\u044c iOS-\u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u0440\u0435\u0434\u0438 QA \u0441 \u0444\u043b\u0430\u0433\u043e\u043c debug, \u0445\u043e\u0442\u044f \u043a\u0430\u043d\u0430\u043b \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u043b\u0438\u0437\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f, \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u043e\u0447\u0435\u043d\u044c \u0448\u0438\u0440\u043e\u043a\u0438. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 static const \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e AppEnvironment \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0432 json \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u043f\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443 \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<p>  <\/p>\n<h1 id=\"lokalizaciya\">\u041b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h1>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"\/img\/image-loader.svg\" data-src=\"https:\/\/habrastorage.org\/webt\/-j\/le\/nb\/-jlenbjc-wvox-vym_unuahmcke.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043f\u0440\u043e \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043d\u0430 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u043d\u043d\u0438\u0445 \u044d\u0442\u0430\u043f\u0430\u0445. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 <a href=\"https:\/\/pub.dev\/packages\/easy_localization\">easy_localization<\/a>. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043d\u0438\u043c \u043f\u0440\u043e\u0448\u043b\u0430 \u0433\u043b\u0430\u0434\u043a\u043e, \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0435\u043d\u0438\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0435 \u0432\u044b\u0437\u0432\u0430\u043b\u0430. <\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0443\u0434\u043e\u0431\u043d\u044b\u043c API. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u0432 background-\u0441\u0435\u0440\u0432\u0438\u0441\u0435 (\u0438\u043b\u0438 \u0438\u0437\u043e\u043b\u044f\u0442\u0435), \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0432\u0438\u0434\u0436\u0435\u0442 EasyLocalization. \u0412\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0438\u0437\u043e\u043b\u044f\u0442\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 easy_localization:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">if (fromBackground) {     final easyLocalizationController = EasyLocalizationController(       supportedLocales: const [SupportedLocales.russianLocale],       fallbackLocale: SupportedLocales.russianLocale,       path: 'assets\/translations',       useOnlyLangCode: true,       saveLocale: true,       assetLoader: const RootBundleAssetLoader(),       useFallbackTranslations: false,       onLoadError: (e) {         GetIt.I.get&lt;Logger>().w('EasyLocalization background error', e);       },     );     await easyLocalizationController.loadTranslations();     Localization.load(       easyLocalizationController.locale,       translations: easyLocalizationController.translations,       fallbackTranslations: easyLocalizationController.fallbackTranslations,     );     easyLocalizationController.locale;   }<\/code><\/pre>\n<p>  <\/p>\n<p>easy_location \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e Logger \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0435\u0440\u0442\u043a\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">@singleton class EasyLoggerWrapper {   final Logger _logger;    EasyLoggerWrapper(this._logger);    void log(     Object object, {     String? name,     LevelMessages? level,     StackTrace? stackTrace,   }) {     switch (level) {       case LevelMessages.info:         _logger.i('[$name] $object', null, stackTrace);         break;       case LevelMessages.warning:         _logger.w('[$name] $object', null, stackTrace);         break;       case LevelMessages.error:         _logger.e('[$name] $object', null, stackTrace);         break;       default:         _logger.d('[$name] $object', null, stackTrace);         break;     }   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 easy_location \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043b\u044e\u0447\u0435\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">flutter pub run easy_localization:generate --source-dir assets\/translations -f keys -o locale_keys.g.dart<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0442\u0430\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 IDE \u0438\u0445 \u00ab\u043d\u0435 \u0432\u0438\u0434\u0438\u0442\u00bb\u200e \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0430\u0432\u0442\u043e\u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u00ab\u043a\u043e\u0441\u0442\u044b\u043b\u0451\u043c\u00bb\u200e \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0432 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"dart\">export 'package:ati_template\/generated\/locale_keys.g.dart'; export 'package:easy_localization\/easy_localization.dart';<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u2014 <a href=\"https:\/\/pub.dev\/packages\/flutter_gen\">flutter_gen<\/a>. <\/p>\n<p>  <\/p>\n<h1 id=\"nasha-cel\">\u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c<\/h1>\n<p>  <\/p>\n<p>\u041c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u0425\u0430\u0431\u0440. \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/atidev\/ATI.SU-Flutter-Template-Project\">\u0448\u0430\u0431\u043b\u043e\u043d-\u043f\u0440\u0438\u043c\u0435\u0440<\/a> \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0432\u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432 \u0432 Flutter-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0432 ATI.SU. \u041a\u0430\u043a\u0438\u0435-\u0442\u043e \u0432\u0435\u0449\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0412\u0430\u0441 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438, \u043d\u043e \u043c\u044b \u043d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0447\u0442\u043e-\u0442\u043e \u0446\u0435\u043d\u043d\u043e\u0435 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c \u2014 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u0438\u0437\u0430\u0446\u0438\u044f Flutter-\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0443\u0441\u0441\u043a\u043e\u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435.\u00a0\u0412\u043c\u0435\u0441\u0442\u0435 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u0440\u0443\u0442\u044b\u0445 \u0432\u0435\u0449\u0435\u0439!<\/p>\n<p>  <\/p>\n<h1 id=\"v-kachestve-zaklyucheniya\">\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/h1>\n<p>  <\/p>\n<p>\u0421 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u043c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u044b\u043d\u043a\u0430 \u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 \u043e\u0441\u0442\u0440\u0435\u0435 \u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0441\u0442\u043e\u043c, \u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041f\u043e \u043e\u043f\u044b\u0442\u0443 \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0432\u044b\u0431\u043e\u0440 Flutter \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0435\u0431\u044f \u043e\u043f\u0440\u0430\u0432\u0434\u044b\u0432\u0430\u0435\u0442. <\/p>\n<p>  <\/p>\n<p>Flutter \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u043d\u043e \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 UI. \u0415\u0449\u0451 \u044d\u0442\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f UX, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412 <a href=\"https:\/\/ati.su\">ATI.SU<\/a> \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442, \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u0435\u0449\u0451 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430 \u0425\u0430\u0431\u0440. \u0412\u043e\u0442 \u043f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u0442\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0442\u043e\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0441\u0432\u0435\u0442\u0438\u0442\u044c:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041c\u043e\u0434\u0443\u043b\u044f\u0440\u0438\u0437\u0430\u0446\u0438\u044f Flutter-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0410 \u0435\u0441\u0442\u044c \u043b\u0438 \u0441\u043c\u044b\u0441\u043b?<\/li>\n<li>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c Flutter \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0418\u0441\u0442\u043e\u0440\u0438\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043d\u0435 \u043d\u0430\u0436\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0432\u0440\u0430\u0433\u043e\u0432 \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445.<\/li>\n<li>\u0423\u043f\u0440\u043e\u0449\u0430\u0435\u043c \u0436\u0438\u0437\u043d\u044c \u0440\u0443\u0447\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432: \u043a\u0430\u043a \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Flutter-\u0444\u0438\u0447.<\/li>\n<li>CI\/CD, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u043d\u0430 dart: \u0432\u043d\u0435\u0434\u0440\u044f\u0435\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0442\u0430\u043c, \u0433\u0434\u0435 \u043e\u043d\u0430, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435 \u043d\u0443\u0436\u043d\u0430.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0425\u043e\u0442\u0438\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0435\u0449\u0435? \u0411\u0443\u0434\u0435\u043c \u0440\u0430\u0434\u044b \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438.<\/p>\n<p>  <\/p>\n<p><em>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0441\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/atidev\/ATI.SU-Flutter-Template-Project\/tree\/main\/lib\/arch\">arch \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a>, \u043d\u043e \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043c\u044b \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0432 pub.dev. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u0441\u0442\u0430\u0442\u044c\u044e \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b.<\/em> <\/p>\n<p>  <\/p>\n<p><strong>FLUTTER is FUN !<\/strong><\/p>\n<\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/atisu\/blog\/597709\/\"> https:\/\/habr.com\/ru\/company\/atisu\/blog\/597709\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\" class=\"article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/6-\/yh\/bn\/6-yhbncdpelvfswcscqzzzkhxp8.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/6-\/yh\/bn\/6-yhbncdpelvfswcscqzzzkhxp8.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<h1 id=\"pro-nas\">\u041f\u0440\u043e \u043d\u0430\u0441<\/h1>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u044b <a href=\"https:\/\/habr.com\/ru\/users\/levitckii-daniil\/\">\u0414\u0430\u043d\u0438\u0438\u043b \u041b\u0435\u0432\u0438\u0446\u043a\u0438\u0439 <\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/users\/wardrone\/\">\u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0414\u0440\u043e\u043d\u043e\u0432<\/a>, \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 <a href=\"https:\/\/ati.su\">ATI.SU<\/a> \u2014 \u043a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0435\u0439 \u0432 \u0420\u043e\u0441\u0441\u0438\u0438 \u0438 \u0421\u041d\u0413 \u0411\u0438\u0440\u0436\u0435 \u0433\u0440\u0443\u0437\u043e\u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043e\u043a. \u0425\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0441\u0432\u043e\u0438\u043c \u0432\u0438\u0434\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Flutter. <\/p>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0438 \u0440\u0430\u043d\u044c\u0448\u0435 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u043e \u043c\u0438\u0440 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 Flutter. \u0423 \u043d\u0430\u0441, \u043a\u0430\u043a \u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0431\u044b\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u043f\u044b\u0442 \u0432 \u044d\u0442\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041d\u043e \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u0440\u0443\u043f\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0441 \u043f\u0440\u0438\u0446\u0435\u043b\u043e\u043c \u043d\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u0442\u0430\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0435 \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0420\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u044b \u0441\u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u043b\u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d-\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u043e\u0432\u044b\u0445 Flutter-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-327454","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/327454","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=327454"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/327454\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=327454"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=327454"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=327454"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}