Šajā apmācībā mēs izskaidrosim kā Android darbojas, palaižot pakalpojumu, mēs aprakstīsim, no kā sastāv izpildes pavedieni un kādi ir procesi. Tas ļaus mums saprast mūsu lietojumprogrammu darbības veidu, nodrošinot lielāku kontroli un stabilitāti mobilajās ierīcēs, kur tās tiks instalētas.
Vītne
Kad lietotājs palaiž lietojumprogrammu, Android izveido pavedienu ar nosaukumu galvenais (galvenais). Šis pavediens ir ļoti svarīgs, jo tas ir atbildīgs par to notikumu pārvaldību, kurus lietotājs izraisa atbilstošajām sastāvdaļām, kā arī ietver notikumus, kas zīmē ekrānu. Izpildes pavediens, mazākā daļa, ko var apstrādāt plānotājs operētājsistēmā, šajā gadījumā Android (ar Linux kodolu).
vairāku pavedienu ieviešana kas tiek apstrādāti vienā un tajā pašā lietojumprogrammā (to sauc par vienlaicīgumu, kas attiecas uz izpildes vienlaicīgumu), to sauc par daudzpavedienu. Daudzpavedieni tiek lietoti, lai šie pavedieni koplietotu resursus Un tas ir process, ko atcerieties, atcerieties, ka to var programmatiski piemērot vienas un tās pašas lietojumprogrammas koda ietvaros, daudzpavedienu ieviešana operētājsistēmas līmenī nav atkarīga no mums.
Lietojumprogrammas dzīves cikla sākums ietver jauna Linux procesa ģenerēšanu, kam tiek piešķirts galvenais pavediens vai lietotāja saskarnes pavediens (pavediens, kas ir atbildīgs par lietojumprogrammas grafisko apstrādi, lietotāja saskarnes pavediens angļu valodā).
PiezīmeDzīves cikls ietver metožu izpildi: onCreate (), onStart () un onResume (); sākumā un beigās: onPause (), onStop () un onDestroy ().
Android var piespiest procesu slēgt atmiņas trūkuma dēļ; šāda veida lietas ir reti sastopamas tehnoloģiju attīstības dēļ, taču tas joprojām notiek.
Jautājums ir šāds: Kādus procesus Android nolemj slēgt?
Tos noslēdz, salīdzinot to svarīguma pakāpi, un tas ir apkopots šādi:
Vissvarīgākais: priekšplāna procesiLietotājs mijiedarbojas ar minēto procesu (minētā procesa metode onResume () pašlaik darbojas). Ir pakalpojums, kas izmanto savas dzīves cikla metodes. Vai arī tur ir a BroadcastReceiver skrienot savu onRecept () metode.
Otrs svarīgākais: redzamie procesiDarbība ar zvanu uz onPause () metode. Pakalpojums, kas saistīts ar redzamu darbību (saistīts pakalpojums).
Trešais svarīgākais: process ar pakalpojumuLietotājs tieši nesadarbojas ar procesu. Procesā fonā darbojas pakalpojums.
Otrs vismazāk svarīgais: fona processNav nekāda veida mijiedarbības ar lietotāju. Pēdējais lietotāja skatītais process tiks iznīcināts pēdējais.
Vismazākais: tukšs processTam nav aktīvu sastāvdaļu. Kešatmiņas saglabāšanas nolūkos process joprojām ir dzīvs, neļaujot lietotājam atgriezties pie šī procesa izmantošanas.
Pēdējais, tukšais process, ir pirmais, kas tiek pārtraukts atmiņas trūkuma gadījumā. Tādējādi lietojumprogramma, kas īsteno pakalpojumu, kurā tiek izveidots pavediens, lai lejupielādētu saturu no interneta, būs svarīgāka par lietojumprogrammu, kas izveido pavedienu, neīstenojot pakalpojumu, tāpēc, visticamāk, tā tiks pārtraukta pirms lejupielādes pabeigšanas. , jo tie ir ilgstoši procesi.
Lai saprastu ,. multhreading redzēsim, kā Android apstrādā savu galveno pavedienu.
PROCESS A ir UI vai GALVENĀ vītne, šis pavediens apstrādā a ziņu rinda vai ziņu rinda, kas darbojas, pavedienam kļūstot dīkstāvē, kurš to apstrādā? Looper.
Looper ir lietotāja interfeisa klase Android Java ka kopā ar Hendleru klase, apstrādā lietotāja saskarnes notikumus, piemēram, pogu nospiešanu, ekrānu pārzīmēšanu un orientācijas slēdžus. Notikumus var izmantot arī, lai ielādētu saturu HTTP pakalpojumā, mainītu attēlu izmērus un izpildītu attālos pieprasījumus. Šo klašu galvenā iezīme ir tā, ka tās spēj ieviest vienlaicīguma modeli.
Android Looper klase satur a MessageQueue (ziņu rinda) un ir saistīta tikai ar tēmu, no kuras tā tika izveidota. Lūdzu, ņemiet vērā, ka šo savienojumu nevar pārtraukt un ka lLooper to nevar piestiprināt nevienam citam pavedienam. Turklāt cilpa atrodas lokālajā krātuvē, un to var izsaukt tikai no statiskas metodes. Pakāpeniska metode pārbauda, vai cilpa jau ir saistīta ar pavedienu, un pēc tam statiskā metode izveido cilpu. Pēc tam cilpu var izmantot, lai pārbaudītu rindā esošos ziņojumus.
Līdz šim mēs saprotam vairākus jēdzienus: process, pavediens, lietotāja saskarnes pavediens, cilpa, bet mēs joprojām nezinām, kāpēc daudzpavedienu.
Ilgtermiņa operācijas
Jebkura metode, kuras izpilde pārsniedz 5 sekundes, tiek uzskatīta par ilgu, kas izraisa tipisku ziņojumu “lietojumprogramma nereaģē. Vai vēlaties to aizvērt?
Kādas var būt šīs darbības?: Piekļuve internetam, SQL vaicājumi, XML / HTML / JSON parsēšana, sarežģīta grafikas apstrāde. Jebkura no šīm darbībām, kas tiek veiktas galvenajā pavedienā, to bloķēs, un, tā kā tā ir tā, kas apstrādā grafisko lietotāja saskarni, tā tiek interpretēta kā iesaldēšana, kuru Android nolemj slēgt.
Iedomāsimies, ka jebkura no šīm darbībām ilgst 7 sekundes un lietotājs nolemj kaut ko ierakstīt kādā teksta ievadē, tāpēc, kamēr šīs 7 sekundes nav pagājušas, lietotāja saskarnes pavediens nevar atjaunināt skatu tā, lai lietotājs novērtētu, ka viņš raksta, un tā tiek ģenerēta iesaldēšana, tiek parādīts ziņojums "bez atbildes", ar kuru jums ir divas iespējas - gaidīt vai iznīcināt, lai gan nekad nevar zināt, cik ilgi jāgaida, tas var būt dažas sekundes vai pat minūtes atkarībā no ziņojumu rindas kuriem ir galvenais pavediens.
Kā izvairīties no sasalšanas?
Izmantojot pavedienus vai pakalpojumus, atkarībā no tā, vai uzdevumam ir jāmaina skats, šajā gadījumā pakalpojums tiek ieviests, jo lietojumprogrammas skatu nevar mainīt ārpus lietotāja saskarnes pavediena. Labākais veids, kā izvairīties no sasalšanas, ir izmantot asinhronos uzdevumus ar klasi AsyncTask. Šajā apmācībā mēs ieviesīsim vairākus pavedienus, lai izprastu Android arhitektūras uzvedību.
Kods un attīstība
Projekts, kuru mēs izveidosim tālāk pamatā būs attēla lejupielāde ar kuru mums ir jāizveido pavediens, kas ļauj mums pārvaldīt piekļuvi un lejupielādēt internetā, jo GALVENĀ vai UI pavediens neatļauj šo darbību.
Mēs sāksim, izveidojot jaunu projektu ar tukšu darbību, mēs esam nosaukuši šo projektu "Vairāku pavedienu piemērs", ar vienu vienkāršu darbību mēs izveidosim XML faila struktūru kas pieder pie šīs aktivitātes.
Mums ir teksta lauks, poga, lineārs izkārtojums, kas atbilst nenoteiktai ielādes joslai, kuru izmantosim vēlāk, un saraksta skats, kurā ir ietverts internetā izvietotu attēlu URL masīvs. Failā, kurā ir Java klase mūsu (unikālajām) darbībām, tas ir rakstīts ar šādu kodu:
pakotne com.omglabs.multithreaexample; importēt android.support.v7.app.AppCompatActivity; importēt android.os.Bundle; importēt android.view.View; importēt android.widget.AdapterView; importēt android.widget.EditText; importēt android.widget.LinearLayout; importēt android.widget.ListView; importēt android.widget.ProgressBar; publiskās klases MainActivity paplašina AppCompatActivity īsteno AdapterView.OnItemClickListener {private EditText editText; privāts ListView listView; privāts String [] URL; privātā ProgressBar progressBar; privāts 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 (šis); URL = getResources (). getStringArray (R.array.URLs); progressBar = (ProgressBar) findViewById (R.id.progressbar); progressLayout = (LinearLayout) findViewById (R.id.progresslayout); } public void download (Skatīt skatu) {} @Override public void onItemClick (AdapterView adapterView, View view, int i, long l) {editText.setText (URL [i]); }}Līdz šim lietojumprogrammu var apkopot bez problēmām, šajā klasē mēs deklarējam mainīgos:
- editText
- listView
- URL
- progressBar
- progressLayout
Teksta lauks, saraksts, virkņu izkārtojums, progresa josla un lineārs izkārtojums.
Iekš onCreate metode Mēs tiem piešķiram atbilstošo skatu, kas tiem pieder un kas tika izveidoti aktivitātes XML failā, izņemot URL, kas piešķir vērtības no virkņu faila vērtību mapes un kuru izkārtojums ir deklarēts sekojoši:
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.webpTukšā lejupielādes metode (skata skats) tiks aizpildīta ar kodu, ar kuru tiks veikta lejupielāde un kas ir saistīts ar Lejupielādes poga Bot izmantojot onclick atribūtu. Visbeidzot ,. onitemclick metode kas pieder saraksta skats, tas aizpilda teksta lauku, noklikšķinot uz jebkura no sarakstā iekļautajiem URL. Kad kods ir apkopots, tas izskatīsies šādi:
Nākamajā solī mēs izveidosim metodes, kas tiks lejupielādētas, veicot šādas darbības:
- Izveidojiet URL klases objektu (java.net), kas attēlo lejupielādējamo URL.
- Atveriet savienojumu, izmantojot šo objektu.
- Izlasiet datus (izmantojot tīmekli), izmantojot baitu masīva ievades plūsmas klasi.
- Atveriet / izveidojiet izvades straumes failu, kurā URL dati tiks saglabāti SD kartē.
- Ierakstiet datus šajā failā.
- Un visbeidzot pārtrauciet savienojumu.
Pagaidām tas izskatīsies šādi:
publiska Būla lejupielāde, izmantojotThreads (String link) {Būla apstiprinājums = false; URL downloadLink = null; HttpURLConnect connect = null; InputStream inputStream = null; mēģiniet {downloadLink = jauns URL (saite); savienojums = (HttpURLConnection) downloadLink.openConnection (); inputStream = connect.getInputStream (); } catch (MalformedURLException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); } beidzot {if (connectx! = null) {connectx.disconnect (); } if (inputStream! = null) {try {inputStream.close (); } catch (IOException e) {e.printStackTrace (); }}} atgriešanās apstiprinājums; }Šai mūsu izveidotajai metodei būs nepieciešams tikai a Stīga kas būs lejupielādējamais URL, ir Būla Lai apstiprinātu lejupielādi, downloadLink ir URL objekts, savienojums ir savienojums, kas tiks izveidots, lai piekļūtu objektam un inputStream ir tas, kas turpinās lasīt datus, ja mēs mēģināsim izmantot šo metodi uz pogas downloadBot lietojumprogramma tiks pārtraukta, jo nevarēs darboties galvenais pavediens.
Šeit mēs izmantojam pavedienus, ir divi veidi, kā to izdarīt ar klasi, un, paplašinot šo klasi līdz pavedienam vai ieviešot klasi Runnable, šī klase nav pavediens, tā vienkārši ļauj jums izveidot metodi, kuru jūs var palaist konkrētā brīdī un, ja izveidojat atsevišķu pavedienu, palaidiet to tajā.
Lejupielādes pogas iekšpusē mēs ierakstīsim šo kodu, un tas izskatīsies šādi:
public void download (Skatīt skatu) {Thread mThread = new Thread (new mRunn ()); mThread.start (); }Šeit mēs veidojam jaunu pavedienu, kuram nepieciešams Runnable objekts, ko mēs izveidojam privātā klasē:
privātā klase mRunn īsteno Runnable {@Override public void run () {download usingThreads (url [0]); }}Izveidojiet privātu klasi
PiezīmeAtcerieties, ka tas viss ir mūsu vienīgās darbības Java klasē.
Ar līniju:
lejupielādēt, izmantojotThreads (URL [0]);Mēs izsaucam funkciju, kuru izveidojām, kad atvērām savienojumu, tai tiek nosūtīts URL masīva vienums, lai tas varētu nolasīt datus no šīs adreses. Vēlāk tas tiks pārveidots.
Ja mēs mēģinātu palaist šo lietojumprogrammu, nospiežot pogu, tā tiktu apturēta, jo mums ir nepieciešama īpaša atļauja, lai piekļūtu internetam, kas tiek pieprasīts, izmantojot mūsu lietojumprogrammas manifestu. Rindas pievienošana pirms etiķetes:
Tagad, lai pārbaudītu, vai lietojumprogramma faktiski veic lejupielādi, mēs pievienosim kodam dažas rindiņas lejupielādes metode, izmantojot Threads, tas izskatīsies šādi:
publiska Būla lejupielāde, izmantojotThreads (String saite) {Būla apstiprinājums = false; URL downloadLink = null; HttpURLConnect connect = null; InputStream inputStream = null; FileOutputStream archOutputStream = null; Faila fails = null; mēģiniet {downloadLink = jauns URL (saite); savienojums = (HttpURLConnection) downloadLink.openConnection (); inputStream = connect.getInputStream (); fails = jauns fails (Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS) + "/" + Uri.parse (saite) .getLastPathSegment ()); archOutputStream = jauns FileOutputStream (fails); int Lasīt = -1; baits [] buferis = jauns baits [1024]; while ((Lasīt = inputStream.read (buferis))! = -1) {archOutputStream.write (buferis, 0, lasīšana); } apstiprinājums = taisnība; } catch (MalformedURLException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); } beidzot {if (connectx! = null) {connectx.disconnect (); } if (inputStream! = null) {try {inputStream.close (); } catch (IOException e) {e.printStackTrace (); }} if (archOutputStream! = null) {try {archOutputStream.close (); } nozveja (IOException e) {e.printStackTrace (); }}} atgriešanās apstiprinājums; } FileOutputStream archOutputStream = null; Faila fails = null;Šo objektu deklarācijas attēlo lasāmā faila rakstīšanu un tukšo failu, kurā lasījums tiks saglabāts.
fails = jauns fails (Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS) + "/" + Uri.parse (URL [0]). getLastPathSegment ()); archOutputStream = jauns FileOutputStream (fails); int Lasīt = -1; baits [] buferis = jauns baits [1024]; while ((Lasīt = inputStream.read (buferis))! = -1) {archOutputStream.write (buferis, 0, lasīšana); } apstiprinājums = taisnība;"Fails" ir tukšs faila objekts, kura adrese tiek veidota, piekļūstot SD kartei "Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS)" un pievienojot slīpsvītru "/" un URL pēdējo segmentu, kas parasti attēlo faila nosaukumu. lejupielādējot, mēs to sasniedzam ar metodi getLastPathSegment ().
Pirms lietojumprogrammas pārbaudes mēs manifestam pievienosim pēdējo atļauju:
Pēc lietojumprogrammas palaišanas emulatorā vai Android ierīcē, nospiežot pogu, mēs redzēsim, ka acīmredzot nekas nenotiek, bet, ja ar failu pārlūku pārbaudīsim mapi Lejupielādēt, mēs sapratīsim, ka pirmais vienums sarakstā ir lejupielādēts; foto ar nosaukumu 1.jpg.webp.
Lai to izdarītu dinamisku lietojumprogrammu un ievieš saraksta skata URL, mēs atjaunināsim lejupielādes metode (skata skats) un mēs to pievienosim kā pirmo rindu:
String saite = editText.getText (). ToString ();Un mRunn klase mēs pievienosim to pirms run () metodes:
privātā klase mRunn īsteno Runnable {private String link; public mRunn (String link) {this.link = saite; } @Override public void run () {lejupielādēt, izmantojotThreads (saite); }}Un mRunn klase mēs pievienosim to pirms run () metodes:
Tātad mēs varam pārsūtīt saites mainīgo no teksta lauka uz metodi, kas veic lejupielādi. Lietojumprogramma šajā brīdī ir pilnībā funkcionāla, lai gan tai trūkst lietotājam draudzīguma, tāpēc mēs centīsimies to novērst, izmantojot sākumā norādīto progresa joslu.
MRunn klasē run () metodē mēs iekļausim:
MainActivity.this.runOnUiThread (jauns Runnable () {@Orride public void run () {progressLayout.setVisibility (View.VISIBLE);}});Pirms zvana uz downloadusandoThreads. Tādējādi, nospiežot pogu, pēdējā klauzulā parādīsies ielādes josla lejupielādes metode, izmantojot Threads.
Mēs pievienosim:
this.runOnUiThread (new Runnable () {@Override public void run () {progressLayout.setVisibility (View.GONE);}});Tātad, kad lejupielāde ir pabeigta, josla atkal pazūd. Tas notiks neatkarīgi no tā, vai lejupielāde ir veiksmīga.
Un tas ir bijis viss, viens vairāku pavedienu īsa ieviešanaTas ir nedaudz garlaicīgi un rada sarežģījumus sarežģītākām lietojumprogrammām.Visefektīvākais veids, kā izpildīt šo uzdevumu, mūsu gadījumā lejupielādējot dažus attēlus, ir AsyncTasks.