„Android“ programa: procesai, temos ir paslaugos

Šioje pamokoje mes paaiškinsime kaip veikia „Android“ veikiant paslaugai, aprašysime, iš ko susideda vykdymo gijos ir kokie yra procesai. Tai leis mums suprasti, kaip veikia mūsų programos, suteikdami mums daugiau valdymo ir stabilumo mobiliuosiuose įrenginiuose, kuriuose jie bus įdiegti.

Siūlai


Kai vartotojas paleidžia programą, „Android“ sukuria giją, vadinamą pagrindine (pagrindine). Ši gija yra labai svarbi, nes ji yra atsakinga už įvykių, kuriuos vartotojas sukelia atitinkamiems komponentams, valdymą, taip pat apima įvykius, kurie piešia ekraną. Vykdymo gija, mažiausia dalis, kurią gali apdoroti planuotojas operacinėje sistemoje, šiuo atveju „Android“ (su „Linux“ branduoliu).

The kelių gijų įgyvendinimas kurie yra apdorojami tuo pačiu metu toje pačioje programoje (tai vadinama lygiagrečiu, kuris reiškia vykdymo vienu metu), jis žinomas kaip daugiasluoksnis. Taikomas kelių gijų siūlas, kad šios gijos pasidalintų ištekliais Ir tai yra procesas, atminkite, kad tai galima programiškai pritaikyti pagal tos pačios programos kodą, daugiasluoksnio diegimas operacinės sistemos lygiu nepriklauso nuo mūsų.

Į programos gyvavimo ciklo pradžią įeina naujo „Linux“ proceso sukūrimas, kuriam priskiriama pagrindinė gija arba vartotojo sąsajos gija (gija, atsakinga už grafinį programos apdorojimą, vartotojo sąsajos gija anglų kalba).

PastabaĮ gyvavimo ciklą įeina metodų vykdymas: onCreate (), onStart () ir onResume (); jo pradžioje ir pabaigoje: onPause (), onStop () ir onDestroy ().

Procesas gali būti priverstas uždaryti „Android“ dėl atminties trūkumo, tokio tipo atvejai yra reti dėl technologinės pažangos, tačiau vis tiek pasitaiko.

Klausimas toks: Kuriuos procesus „Android“ nusprendžia uždaryti?

Jie baigiami lyginant jų svarbos lygį, jis apibendrinamas taip:

Svarbiausia: pirmojo plano procesaiVartotojas sąveikauja su minėtu procesu (šiuo metu veikia minėto proceso metodas onResume ()). Yra paslauga, kuri naudoja savo gyvavimo ciklo metodus. Arba yra a „BroadcastReceiver“ bėgdamas savo onRecept () metodas.

Antras svarbiausias: matomi procesaiVeikla su skambučiu onPause () metodas. Paslauga, susieta su matoma veikla (susieta paslauga).

Trečias svarbiausias: procesas su paslaugaNaudotojas tiesiogiai nesąveikauja su procesu. Proceso fone veikia paslauga.

Antras mažiausiai svarbus: fono procesasNėra jokio sąveikos su vartotoju tipo. Procesas, kurį paskutinį kartą peržiūrėjo vartotojas, bus sunaikintas paskutinis.

Mažiausiai svarbu: tuščias procesasJame nėra aktyvių komponentų. Procesas vis dar gyvas talpykloje, neleidžiantis vartotojui grįžti prie to proceso naudojimo.

Pastarasis, tuščias procesas, pirmasis nutraukiamas, jei trūksta atminties. Taigi, programa, įgyvendinanti paslaugą, kurioje sukurta gija, skirta atsisiųsti turinį iš interneto, bus svarbesnė už programą, kuri sukuria temą neįdiegusi paslaugos, todėl didesnė tikimybė, kad ji bus nutraukta prieš baigiant atsisiuntimą. , nes jie yra ilgalaikiai procesai.

Norėdami suprasti ,. daugiasluoksniai, pažiūrėkime, kaip „Android“ tvarko pagrindinę temą.

PROCESAS A turi vartotojo sąsają arba PAGRINDINIS siūlas, šis siūlas tvarko a pranešimų eilė ar pranešimų eilė, kuri veikia, kai gija tampa tuščia, kas tai tvarko? The Looper.

„Looper“ yra vartotojo sąsajos klasė „Android“ „Java“ kad kartu su Hedlerio klasė, apdoroja vartotojo sąsajos įvykius, tokius kaip mygtukų paspaudimai, perbraižyti ekranai ir orientacijos jungikliai. Įvykiai taip pat gali būti naudojami įkeliant turinį į HTTP paslaugą, keičiant vaizdų dydį ir vykdant nuotolines užklausas. Pagrindinis šių klasių bruožas yra tas, kad jie gali įgyvendinti lygiagrečių modelį.

The „Android Looper“ klasė yra a „MessageQueue“ (pranešimų eilė) ir yra susieta tik su tema, iš kurios ji buvo sukurta. Atminkite, kad šio ryšio negalima nutraukti ir kad lLooper jo negalima pritvirtinti prie kitos temos. Be to, „Looper“ yra vietinėje saugykloje ir gali būti iškviestas tik naudojant statinį metodą. Stebėjimo metodas patikrina, ar ciklas jau susietas su gija, tada statinis metodas sukuria ciklą. Po to ciklas gali būti naudojamas pranešimams eilėje patikrinti.

Iki šiol mes suprantame keletą sąvokų: procesas, gija, vartotojo sąsajos siūlas, kilpas, bet mes vis dar nežinome, kodėl daugiasluoksnis.

Ilgalaikės operacijos


Laikoma, kad bet kuris metodas, kurio vykdymas viršija 5 sekundes, trunka ilgai, o tai sukelia įprastą pranešimą „programa nereaguoja. Ar norite jį uždaryti?

Kokios gali būti šios operacijos?: Interneto prieiga, SQL užklausos, XML / HTML / JSON analizavimas, sudėtingas grafikos apdorojimas. Bet kuri iš šių operacijų, vykdomų pagrindinėje gijoje, ją užblokuos, o kadangi grafinę vartotojo sąsają tvarko būtent ji, ji aiškinama kaip užšaldymas, kurį „Android“ nusprendžia uždaryti.

Įsivaizduokime, kad bet kuri iš šių operacijų trunka 7 sekundes ir vartotojas nusprendžia ką nors parašyti įvesdamas tam tikrą tekstą, taigi, kol šios 7 sekundės nepraėjo, vartotojo sąsajos gija negali atnaujinti rodinio taip, kad vartotojas suprastų, jog rašo, ir Taigi jis užšaldo, suaktyvinamas pranešimas „nereaguojama“, kuriame yra dvi galimybės: laukti arba sunaikinti, nors niekada negali žinoti, kiek reikia laukti, tai gali užtrukti kelias sekundes ar net minutes, priklausomai nuo pranešimų eilės kurie turi pagrindinę giją.

Kaip išvengti užšalimo?


Naudojant gijas ar paslaugas, atsižvelgiant į tai, ar užduočiai reikia keisti rodinį, šiuo atveju paslauga įgyvendinama, nes programos rodinio negalima keisti už vartotojo sąsajos srities ribų. Geriausias būdas išvengti užšalimo yra naudoti asinchronines užduotis su „AsyncTask“ klase. Šioje pamokoje mes įgyvendinsime kelias gijas, kad suprastume „Android“ architektūros elgesį.

Kodas ir plėtra


Projektas, kurį kursime toliau bus pagrįstas atsisiunčiamu paveikslėliu su kuria turime sukurti temą, leidžiančią mums valdyti prieigą ir atsisiųsti internetu, nes PAGRINDINIS arba UI gija neleidžia atlikti šio veiksmo.

Pradėsime kurdami naują projektą su tuščia veikla, pavadinome šį projektą „MultiThreadEamam“, su viena paprasta veikla sukursime XML failo struktūrą kuri priklauso šiai veiklai.

 
Turime teksto lauką, mygtuką, linijinį išdėstymą, kuris atitinka neapibrėžtą įkėlimo juostą, kurį naudosime vėliau, ir sąrašo rodinį, kuriame yra internete esančių vaizdų URL masyvas. Faile, kuriame yra mūsų (unikalios) veiklos „Java“ klasė, jis parašytas tokiu kodu:
 paketas com.omglabs.multithreaexample; importuoti android.support.v7.app.AppCompatActivity; importuoti android.os.Bundle; importuoti android.view.View; importuoti android.widget.AdapterView; importuoti android.widget.EditText; importuoti android.widget.LinearLayout; importuoti android.widget.ListView; importuoti android.widget.ProgressBar; public class MainActivity išplės AppCompatActivity įgyvendina AdapterView.OnItemClickListener {private EditText editText; private ListView listView; privačios eilutės [] URL; privati ​​„ProgressBar progressBar“; private LinearLayout progressLayout; @Override protected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); editText = [EditText] findViewById (R.id.downloadURL); listView = (ListView) findViewById (R.id.listurls); listView.setOnItemClickListener (tai); URL = getResources (). getStringArray (R.array.URLs); progressBar = (ProgressBar) findViewById (R.id.progressbar); progressLayout = (LinearLayout) findViewById (R.id.progresslayout); } public void download (Rodinio vaizdas) {} @Override public void onItemClick (AdapterView adapterView, View view, int i, long l) {editText.setText (URL [i]); }} 
Iki šiol programą galima sudaryti be jokių problemų, šioje klasėje deklaruojame kintamuosius:
  • editText
  • Sarašas
  • URL
  • progreso juosta
  • progressLayout

Teksto laukas, sąrašas, eilučių išdėstymas, eigos juosta ir linijinis išdėstymas.

Viduje onCreate metodas Mes priskiriame jiems atitinkamą rodinį, kuris jiems priklauso ir kuris buvo sukurtas veiklos XML faile, išskyrus URL, kuris priskiria savo reikšmes iš eilutės failo aplanko reikšmės ir kurio išdėstymas deklaruojamas taip:

 http://www.fmdos.cl/wp-content/uploads/2016/03/1.jpg.webp http://vignette3.wikia.nocookie.net/teenwolf/images/9/90/Crystal_Reed_003.jpeg.webp https: // pbs.twimg.com/profile_images/699667844129107968/EvhTFBHN.jpg.webp http://vignette1.wikia.nocookie.net/teen-wolf-pack/images/0/0b/Holland-holland-roden-31699868-500-600.png.webp 
Tuščias atsisiuntimo būdas (rodinio rodinys) bus užpildytas kodu, kuris atsiųs ir bus susietas su Atsisiuntimo mygtukas Bot per „onclick“ atributą. Galiausiai, onitemclick metodas kuriam priklauso Sarašas, jis užpildo teksto lauką, kai spustelite bet kurį iš sąraše esančių URL. Sukūrus šį kodą, jis atrodys taip:

Kitame žingsnyje sukursime metodus, kurie bus atsisiunčiami, atlikdami šiuos veiksmus:

  • Sukurkite URL klasės objektą (java.net), kuris parodys atsisiunčiamą URL.
  • Atidarykite ryšį naudodami tą objektą.
  • Skaitykite duomenis (per internetą) naudodami įvesties srauto klasę baitų masyve.
  • Atidarykite / sukurkite išvesties srauto failą, kuriame URL duomenys bus išsaugoti SD kortelėje.
  • Įrašykite duomenis į tą failą.
  • Ir galiausiai uždarykite ryšį.

Kol kas tai atrodys taip:

 viešas loginis atsisiuntimas naudojant „Threads“ (eilutės nuoroda) {boolean confirmation = false; URL downloadLink = null; HttpURLConnection connect = null; InputStream inputStream = null; pabandykite {downloadLink = naujas URL (nuoroda); connection = (HttpURLConnection) downloadLink.openConnection (); inputStream = connect.getInputStream (); } sugavimas (netinkamai suformuotaURLE išimtis e) {e.printStackTrace (); } sugauti (IOException e) {e.printStackTrace (); } pagaliau {if (connectx! = null) {connectx.disconnect (); } if (inputStream! = null) {try {inputStream.close (); } sugauti (IOException e) {e.printStackTrace (); }}} grąžinimo patvirtinimas; } 
Šiam mūsų sukurtam metodui reikės tik a Styga kuris bus URL, kurį reikia atsisiųsti, yra loginis Norėdami patvirtinti atsisiuntimą, „downloadLink“ yra URL objektas, ryšys yra ryšys, kuris bus sukurtas norint pasiekti objektą ir įvestis „Stream“ yra tas, kuris toliau skaitys duomenis, jei bandysime naudoti šį metodą ant mygtuko downloadBot programa bus sustabdyta, nes negalės paleisti pagrindinis siūlas.

Čia mes naudojame siūlus, yra du būdai, kaip tai padaryti naudojant klasę, ir išplėsdami šią klasę į temą arba įgyvendindami klasę „Runnable“, ši klasė nėra gija, ji tiesiog leidžia jums sukurti metodą, kurį gali veikti konkrečiu momentu ir, jei sukuriate atskirą temą, paleiskite ją.

Atsisiuntimo mygtuko viduje parašysime šį kodą ir jis atrodys taip:

 public void download (Rodinio vaizdas) {Thread mThread = new Thread (new mRunn ()); mThread.start (); } 
Čia mes kuriame naują giją, kuriai reikia „Runnable“ objekto, kurį sukuriame privačioje klasėje:
 privačios klasės „mRunn“ įgyvendina „Runnable“ {@Override public void run () {download usingThreads (url [0]); }} 
Sukurkite privačią klasę

PastabaAtminkite, kad visa tai yra mūsų vienintelės veiklos „Java“ klasėje.

Su eilute:

 atsisiųsti naudojant „Threads“ (URL [0]);
Skambiname funkcijai, kurią sukūrėme, kai atidarėme ryšį, jam perduodamas URL masyvo elementas, kad jis galėtų nuskaityti duomenis iš to adreso. Vėliau jis bus modifikuotas.

Jei bandytume paleisti šią programą paspausdami mygtuką, programa būtų sustabdyta, nes mums reikia specialaus leidimo prisijungti prie interneto, kurio prašoma per mūsų programos manifestą. Pridėkite eilutę prieš etiketę:

 
Dabar norėdami patikrinti, ar programa iš tikrųjų atlieka atsisiuntimą, prie failo pridėsime kelias kodo eilutes Atsisiuntimo metodas naudojant „Threads“, tai atrodys taip:
 viešas loginis atsisiuntimas naudojant „Threads“ (eilutės nuoroda) {boolean confirmation = false; URL downloadLink = null; HttpURLConnection connect = null; InputStream inputStream = null; FileOutputStream archOutputStream = null; Failo failas = null; pabandykite {downloadLink = naujas URL (nuoroda); connection = (HttpURLConnection) downloadLink.openConnection (); inputStream = connect.getInputStream (); failas = naujas failas (Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS) + "/" + Uri.parse (nuoroda) .getLastPathSegment ()); archOutputStream = naujas FileOutputStream (failas); int Skaitymas = -1; baitas [] buferis = naujas baitas [1024]; while ((Skaitymas = inputStream.read (buferis))! = -1) {archOutputStream.write (buferis, 0, skaitymas); } patvirtinimas = tiesa; } sugavimas (netinkamai suformuotaURLE išimtis e) {e.printStackTrace (); } sugauti (IOException e) {e.printStackTrace (); } pagaliau {if (connectx! = null) {connectx.disconnect (); } if (inputStream! = null) {try {inputStream.close (); } sugauti (IOException e) {e.printStackTrace (); }} if (archOutputStream! = null) {try {archOutputStream.close (); } sugauti (IOException e) {e.printStackTrace (); }}} grąžinimo patvirtinimas; } FileOutputStream archOutputStream = null; Failo failas = null; 
Šių objektų deklaracijos atspindi skaitomo failo rašymą ir tuščią failą, kuriame rodmenys bus išsaugoti.
 failas = naujas failas (Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS) + "/" + Uri.parse (URL [0]). getLastPathSegment ()); archOutputStream = naujas FileOutputStream (failas); int Skaitymas = -1; baitas [] buferis = naujas baitas [1024]; while ((Skaityti = inputStream.read (buferis))! = -1) {archOutputStream.write (buferis, 0, skaityti); } patvirtinimas = tiesa; 
„Failas“ yra tuščias failo objektas, kurio adresas sukonstruotas pasiekiant SD kortelę „Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS)“ ir pridedant pasvirąjį brūkšnį „/“ ir paskutinį URL segmentą, kuris paprastai nurodo failo pavadinimą. atsisiuntę, tai pasiekiame naudodami metodą getLastPathSegment ().

Prieš išbandydami programą, manifeste pridėsime paskutinį leidimą:

 
Paleidę programą emuliatoriuje ar „Android“ įrenginyje, paspausdami mygtuką pamatysime, kad, matyt, nieko neatsitiks, tačiau jei failų naršykle patikrinsime aplanką Atsisiųsti, suprasime, kad pirmasis sąrašo elementas buvo atsisiųstas; nuotrauka pavadinimu 1.jpg.webp.

Padaryti tai dinaminę programą ir įdiegti sąrašo peržiūros URL, mes atnaujinsime atsisiuntimo būdas (peržiūrėti rodinį) ir mes pridėsime tai kaip pirmąją eilutę:

 Styginių nuoroda = editText.getText (). ToString ();
Ir „mRunn“ klasė pridėsime tai prieš metodą run ():
 privačios klasės „mRunn“ įgyvendina „Runnable“ {private String link; public mRunn (String link) {this.link = link; } @Override public void run () {atsisiųsti naudojant „Threads“ (nuoroda); }}
Ir „mRunn“ klasė pridėsime tai prieš metodą run ():

Taigi nuorodos kintamąjį galime perkelti iš teksto lauko į atsisiuntimo metodą. Programa šiuo metu yra visiškai funkcionali, nors jai ir trūksta patogumo vartotojui, todėl bandysime tai ištaisyti naudodami pažangos juostą, kurią paskelbėme pradžioje.

Į mRunn klasę run () metodu mes įtraukiame:

 MainActivity.this.runOnUiThread (new Runnable () {@Orride public void run () {progressLayout.setVisibility (View.VISIBLE);}}); 
Prieš skambinant į downloadusandoThreads. Tai parodys įkėlimo juostą, kai paspausime mygtuką, esantį galutinėje straipsnio dalyje Atsisiuntimo metodas naudojant „Threads“.

Pridėsime:

 this.runOnUiThread (new Runnable () {@Override public void run () {progressLayout.setVisibility (View.GONE);}}); 
Taigi, kai atsisiuntimas bus baigtas, juosta vėl dings. Taip atsitiks, nepaisant to, ar atsisiuntimas buvo sėkmingas.
Ir tai buvo viskas, vienas trumpas kelių gijų įgyvendinimasTai šiek tiek varginantis ir sudėtingesnėms programoms sukelia tam tikrų komplikacijų.Efektyviausias būdas atlikti šią užduotį, mūsų atveju - atsisiųsti kai kuriuos vaizdus, ​​yra AsyncTasks.

wave wave wave wave wave