андройд студи тоглоомын урсгал гэр рүүгээ дарж байна. Процесс ба утаснууд

Өөр ямар ч бүрэлдэхүүн хэсэг ажиллахгүй үед програмын бүрэлдэхүүн хэсэг ажиллаж эхлэх үед Android систем нь програмын шинэ Линукс процессыг нэг урсгалаар гүйцэтгэдэг. Анхдагч байдлаар, нэг програмын бүх бүрэлдэхүүн хэсэг нь ижил процесс болон урсгалаар ажилладаг ("үндсэн хэлхээ" гэж нэрлэдэг). Хэрэв програмын бүрэлдэхүүн хэсэг нь тухайн програмын процесс байх үед ажилладаг бол (учир нь програмын өөр бүрэлдэхүүн хэсэг байдаг) тухайн бүрэлдэхүүн хэсэг нь тухайн процесст ажиллаж, гүйцэтгэх ижил хэлхээг ашигладаг. Гэсэн хэдий ч та бусад програмын бүрэлдэхүүн хэсгүүдийн гүйцэтгэлийг тусдаа процессоор зохион байгуулж, аливаа процесст нэмэлт хэлхээ үүсгэж болно.

Энэхүү баримт бичиг нь Андройд аппликейшн дээр процессууд болон хэлхээнүүд хэрхэн ажилладаг талаар ярилцдаг.

Үйл явц

Анхдагч байдлаар, нэг програмын бүх бүрэлдэхүүн хэсгүүд ижил процессоор ажилладаг бөгөөд ихэнх програмууд энэ үйлдлийг өөрчлөх ёсгүй. Гэсэн хэдий ч, хэрэв та тухайн бүрэлдэхүүн хэсэг нь аль процесст хамаарахыг хянах шаардлагатай бол үүнийг манифест файлд хийж болно.

Бүрэлдэхүүн хэсэг элементийн төрөл бүрийн манифест оруулга нь - , ба - бүрэлдэхүүн хэсэг ажиллах ёстой процессыг тодорхойлох боломжийг олгодог android:process шинж чанарыг дэмждэг. Та энэ шинж чанарыг бүрэлдэхүүн хэсэг бүр өөрийн процессоор ажиллуулах эсвэл зөвхөн зарим бүрэлдэхүүн хэсгүүд ижил процессыг хуваалцахаар тохируулж болно. Та мөн адил Линукс хэрэглэгчийн ID-г хуваалцаж, ижил сертификатаар нэвтэрсэн тохиолдолд өөр өөр програмын бүрэлдэхүүн хэсгүүдийг ижил процесст ажиллуулахын тулд android:process процессыг тохируулах боломжтой.

  • Хоосон үйл явц

    Хэрэглээний идэвхтэй бүрэлдэхүүн хэсгүүд агуулаагүй процесс. Энэ төрлийн процессыг хадгалах цорын ганц шалтгаан нь кэш хийх явдал бөгөөд дараагийн удаа тухайн процесст бүрэлдэхүүн хэсэг ажиллахад сайжирдаг. Систем нь процессын кэш болон үндсэн цөмийн кэш хооронд системийн бүх нөөцийг жигд хуваарилахын тулд эдгээр процессуудыг ихэвчлэн устгадаг.

  • Android систем нь процессыг дээд тал нь гэж ангилдаг өндөр түвшинодоогийн үйл явцад идэвхтэй байгаа бүрэлдэхүүн хэсгүүдийн ач холбогдлыг үндэслэн. Жишээлбэл, хэрэв процесс нь үйлчилгээ болон харагдахуйц үйл ажиллагааг агуулж байвал үйл явцыг үйлчилгээний процесс биш харин харагдахуйц гэж үзнэ.

    Нэмж дурдахад, үүнээс хамаарах бусад процессууд байдаг тул үйл явцын түвшинг ахиулах боломжтой. Жишээлбэл, өөр процесст үйлчилдэг процесс нь үйлчилсэн процессын түвшнээс доогуур түвшинтэй байж болохгүй. Жишээлбэл, хэрэв А процесст байгаа контент нийлүүлэгч нь В процесст байгаа үйлчлүүлэгчид үйлчилдэг эсвэл А үйлчилгээний процесс нь В процессын бүрэлдэхүүн хэсэгтэй холбоотой бол А процессыг үргэлж В процессоос дутуугүй чухал гэж үздэг.

    Үйлчилгээг ажиллуулж буй процесс нь үндсэн үйл ажиллагаатай процессоос өндөр үнэтэй байдаг тул удаан үргэлжилсэн үйл ажиллагааг эхлүүлж байгаа үйл ажиллагаа нь зөвхөн ажилчны хэлхээ үүсгэхийн оронд тухайн үйлдлээр эхэлж болно, ялангуяа үйл ажиллагаа нь тухайн үйл ажиллагаанаас удаан үргэлжилдэг бол. Жишээлбэл, вэб сайтад зураг байршуулах үйл ажиллагаа нь байршуулалтыг гүйцэтгэхийн тулд үйлчилгээг эхлүүлэх шаардлагатай байдаг тул хэрэглэгч үйл ажиллагаанаас гарсны дараа ч байршуулалт нь цаана нь үргэлжлэх боломжтой. Үйлчилгээг ашиглах нь тухайн үйлдэлд юу ч тохиолдсон үйл ажиллагаа нь дор хаяж "үйлчилгээний үйл явц"-ын тэргүүлэх ач холбогдолтой байх болно. Үүнтэй ижил шалтгаанаар хүлээн авагчид зөвхөн удаан хугацаа шаардагддаг урсгалын үйлдлүүдийг бус үйлчилгээг ашиглах ёстой.

    урсгалууд

    Аппликейшн ажиллаж эхлэхэд систем нь програмын гүйцэтгэх хэлхээг үүсгэдэг бөгөөд үүнийг "мастер" гэж нэрлэдэг. Энэ хэлхээ нь үйл явдлуудыг холбогдох хэрэглэгчийн интерфэйсийн виджетүүд, түүний дотор үйл явдлуудыг дамжуулах үүрэгтэй тул маш чухал юм. график дүрслэл. Энэ нь мөн программ нь Android UI хэрэгслийн бүрэлдэхүүн хэсгүүдтэй (ба багцын бүрэлдэхүүн хэсгүүд) харьцдаг утас юм. Үндсэндээ гол утас нь заримдаа UI thread гэж нэрлэгддэг зүйл юм.

    Систем үгүйбүрэлдэхүүн хэсэг бүрийн хувьд тусдаа урсгал үүсгэдэг. Ижил процесст ажиллаж байгаа бүх бүрэлдэхүүн хэсгүүдийг UI урсгал дээр үүсгэсэн бөгөөд бүрэлдэхүүн хэсэг бүрийн системийн дуудлагыг тухайн хэлхээнээс илгээдэг. Тиймээс системийн буцаан дуудлагад хариу үйлдэл үзүүлэх аргууд (хэрэглэгчийн үйлдлийг мэдээлэх арга эсвэл буцаан дуудлагын арга гэх мэт). амьдралын мөчлөг) нь үргэлж процессын UI урсгал дээр гүйцэтгэгддэг.

    Жишээлбэл, хэрэглэгч дэлгэцэн дээрх товчлуурыг дарахад таны программын UI хэлхээ нь виджет рүү товших үйл явдлыг илгээдэг бөгөөд энэ нь товчлуурыг дарагдсан төлөвт тохируулж, үйл явдлын дараалалд цуцлах хүсэлт илгээдэг. UI хэлхээ нь хүсэлтийг дарааллаас гаргаж, виджетийг дахин үзүүлэх шаардлагатайг мэдэгдэнэ.

    Аппликейшн хийх үед эрчимтэй ажилХэрэглэгчийн үйлдлийн хариуд энэ нэг утастай загвар нь програмыг зөв хэрэгжүүлээгүй тохиолдолд гүйцэтгэл муутай байж болно. Өөрөөр хэлбэл, хэрэв бүх зүйл UI урсгал дээр тохиолдвол сүлжээнд нэвтрэх эсвэл мэдээллийн сангийн асуулга гэх мэт удаан үргэлжилсэн үйлдлүүд нь UI-г бүхэлд нь хаах болно. Утас хаагдсан үед дэлгэцийн өөрчлөлтийн үйл явдлуудыг оруулаад ямар ч үйл явдлыг боловсруулах боломжгүй. Хэрэглэгчийн өнцгөөс харахад програм өлгөгдсөн мэт харагдаж байна. Хамгийн муу нь, хэрэв UI утас хэдхэн секундээс илүү хугацаагаар хаагдсан бол (одоогоор 5 секунд орчим) гутамшигтай "харилцах цонх" гарч ирнэ. Үүний дараа сэтгэл дундуур байгаа хэрэглэгч таны програмаас гарч устгаж болно.

    Үүнээс гадна, Android UI Toolkit үгүйутас аюулгүй байна. Тиймээс та ажилчны утаснаас хэрэглэгчийн интерфейс дээр ажиллах ёсгүй. UI зохицуулалтыг UI хэлхээнээс хийх ёстой. Тиймээс Android-ийн нэг урсгалтай загварын зөвхөн хоёр дүрэм байдаг:

    1. UI хэлхээг бүү хаа
    2. UI хэлхээний гаднаас Android UI хэрэгсэлд хандаж болохгүй

    Ажлын урсгал

    Дээр дурдсан нэг урсгалтай загвартай тул UI урсгалыг блоклохгүй байх нь таны програмуудын UI динамизмд маш чухал юм. Хэрэв та хэсэг хугацаа шаардагдах үйлдлүүдийг хийх шаардлагатай бол тэдгээрийг тусдаа урсгалууд дээр ("арын дэвсгэр" эсвэл "ажилчин" утас) гүйцэтгэхээ мартуузай.

    Жишээлбэл, тусдаа урсгалаас зургийг ачаалж, виджет дээр харуулах товшилтын хяналтын кодыг доор харуулав.

    Public void onClick(View v) ( new Thread(new Runnable() ( public void run() ( Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); ) )).эхлэх(); )

    Эхлээд харахад энэ нь сүлжээний үйл ажиллагааг зохицуулах шинэ хэлхээ үүсгэдэг тул сайн ажиллах ёстой. Гэсэн хэдий ч энэ нь нэг урсгалтай загварын хоёр дахь дүрмийг зөрчиж байна: UI хэлхээний гаднаас android UI хэрэгсэлд хандаж болохгүй- Энэ жишээ нь UI урсгалаас биш харин ажилчны хэлхээнээс өөрчилдөг. Энэ нь тодорхойлоход хэцүү, тодорхойгүй, гэнэтийн зан үйлд хүргэж болзошгүй юм.

    Энэ асуудлыг засахын тулд Android нь бусад хэлхээсээс UI хэлхээнд хандах хэд хэдэн аргыг санал болгодог. Ашигтай аргуудын жагсаалтыг доор харуулав.

    Жишээлбэл, та дээрх кодыг дараах аргаар засах боломжтой.

    Public void onClick(View v) ( new Thread(new Runnable() ( public void run() ( эцсийн Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(шинэ Ажиллуулах боломжтой() ) ( public void run() ( mImageView.setImageBitmap(bitmap); ) )); ) )).эхлэх(); )

    Хэрэгжилт нь одоо урсгалд аюулгүй болсон: сүлжээний үйл ажиллагаа нь UI урсгалаас ажиллаж байх үед тусдаа хэлхээнээс хийгдэнэ.

    Гэсэн хэдий ч нарийн төвөгтэй байдал нэмэгдэхийн хэрээр энэ төрлийн код нь төөрөгдүүлж, засвар үйлчилгээ хийхэд хэцүү болдог. Ажилчны хэлхээтэй илүү төвөгтэй харилцан үйлчлэлийг зохицуулахын тулд та UI урсгалаас ирж буй мессежийг зохицуулахын тулд ажилчны хэлхээ дээрх аргыг ашиглаж болно. Хэрэглэгчийн интерфэйстэй харилцах шаардлагатай ажлын урсгалын даалгавруудыг гүйцэтгэхэд хялбар болгодог ангиудыг өргөтгөх нь хамгийн сайн шийдэл байж болох юм.

    AsyncTask ашиглаж байна

    Thread Safe Methods

    Зарим тохиолдолд хэрэгжсэн аргуудыг олон хэлхээнээс дуудаж болох тул урсгалыг аюулгүй байлгахын тулд бичих шаардлагатай.

    Энэ нь үндсэндээ алсаас дуудаж болох аргууд, тухайлбал . Аргын дуудлагыг гүйцэтгэхтэй ижил процессоос үүссэн ангид хэрэгжүүлэх үед арга нь дуудаж буй аргын урсгал дээр ажиллана. Гэсэн хэдий ч, дуудлага өөр процессоос ирэх үед уг арга нь систем нь ижил процесст хадгалдаг урсгалуудын сангаас сонгогдсон урсгал дээр ажилладаг (энэ нь процессын UI урсгал дээр ажилладаггүй). Жишээлбэл, үйлчилгээний аргыг үйлчилгээний процессын UI урсгалаас дуудах тул буцаах объект дээр хэрэгжсэн аргуудыг (жишээ нь, RPC аргыг хэрэгжүүлдэг дэд анги) усан сан дахь урсгалуудаас дуудах болно. Үйлчилгээ нь олон үйлчлүүлэгчтэй байж болох тул олон нэгтгэсэн хэлхээнүүд ижил аргыг нэгэн зэрэг ашиглаж болно. Тиймээс аргуудыг урсгалтай аюулгүй байдлаар хэрэгжүүлэх ёстой.

    Үүний нэгэн адил контент нийлүүлэгч өөр процессоос гаралтай мэдээллийн хүсэлтийг хүлээн авч болно. Ангиуд нь процессууд хэрхэн харилцан үйлчилдэг тухай нарийн ширийн зүйлийг нуудаг ч эдгээр хүсэлтэд хариу өгөх аргууд буюу , болон аргууд нь UI урсгалын процесс дээр биш харин контент нийлүүлэгчийн процесс дээрх урсгалын сангаас дуудагддаг. Эдгээр аргуудыг хэд хэдэн хэлхээнээс нэгэн зэрэг дуудаж болох тул тэдгээрийг урсгалын аюулгүй байдлаар хэрэгжүүлэх ёстой.

    Үйл явцын харилцан үйлчлэл

    Андройд систем нь алсын процедурын дуудлагыг (RPC) ашиглан үйл явцын холбооны (IPC) механизмаар хангадаг бөгөөд арга нь үйл ажиллагаа эсвэл бусад хэрэглүүрийн бүрэлдэхүүнээр дуудагддаг боловч алсаас (өөр процессоор) бүх үр дүнг дуудаж буй бүрэлдэхүүн хэсэг рүү буцаадаг. . Энэ нь аргын дуудлагыг болон түүний өгөгдлийг үйлдлийн системд ойлгомжтой түвшинд задлах, түүнийг локал процесс болон хаягийн орон зайгаас алсын процесс болон хаягийн орон зайд дамжуулж, дараа нь дуудлагыг дахин угсарч, дахин бүтээхэд оршино. Үүний дараа буцаж ирсэн утгууд нь эсрэг чиглэлд дамждаг. Андройд систем нь эдгээр IPC механизмуудыг хэрэгжүүлэх бүх кодыг агуулдаг тул та RPC API-г тодорхойлж, хэрэгжүүлэхэд анхаарлаа төвлөрүүлж болно.

    IPC-г гүйцэтгэхийн тулд програмыг ашиглан үйлчилгээтэй холбогдсон байх ёстой. нэмэлт мэдээлэлхөгжүүлэгчийн гарын авлага хэсэгт үзүүлэв.


    Threads нь бие биедээ саад учруулахгүйгээр олон ажлыг нэгэн зэрэг гүйцэтгэх боломжийг олгодог бөгөөд энэ нь системийн нөөцийг үр ашигтай ашиглах боломжийг олгодог. Удаан үргэлжилсэн нэг үйлдэл нь бусад үйлдэлд саад учруулахгүй байх үед утаснуудыг ашигладаг. Жишээлбэл, бид тоглуулах, түр зогсоох товчлууртай хөгжим тоглуулагчтай. Хэрэв та тоглуулах товчийг дарж, танд тусдаа урсгалаар ажиллаж байгаа хөгжмийн файл байгаа бол файлыг бүрэн тоглуулах хүртэл түр зогсоох товчийг дарж чадахгүй. Threads-ийн тусламжтайгаар та энэ хязгаарлалтыг тойрч гарах боломжтой.

    Арын хэлхээг ашиглах

    Таны аппликейшн хариу үйлдэл үзүүлж байгаа эсэхийг шалгахын тулд бүх удаашралтай, цаг хугацаа шаардсан үйлдлүүдийг програмын үндсэн хэлхээнээс хүүхэд хэлхээ рүү шилжүүлэх нь зүйтэй.

    Үйл ажиллагаа, үйлчилгээ, өргөн нэвтрүүлгийн зорилго хүлээн авагч зэрэг Андройд програмын бүх бүрэлдэхүүн хэсгүүд нь програмын үндсэн урсгал дээр ажиллаж эхэлдэг. Үүний үр дүнд эдгээр бүрэлдэхүүн хэсгүүдийн аль нэгэнд цаг хугацаа шаардсан үйлдлүүд нь програмын бусад бүх хэсгийг, тэр дундаа үйлчилгээ, үйл ажиллагааг тэргүүн эгнээнд блоклодог.

    Арын арын хэлхээний хэрэглээ - шаардлагатай нөхцөлХэрэв та харилцах цонхноос зайлсхийхийг хүсвэл програмыг хүчээр хаах болно. Андройдын үйл ажиллагаа хэрэглэгчийн оруулсан үйл явдалд (товч дарах гэх мэт) 5 секундын турш хариу өгөхгүй эсвэл цацах зорилготой хүлээн авагч зохицуулагчаас гарахгүй байх үед onReceive() 10 секундын дотор өргөдлийг өлгөгдсөн гэж үзнэ. Ийм нөхцөл байдлаас ямар ч үнээр зайлсхийх хэрэгтэй. Файл боловсруулах, сүлжээний хүсэлт, өгөгдлийн сангийн гүйлгээ, нарийн төвөгтэй тооцоолол зэрэг цаг хугацаа шаардсан бүх үйлдлүүдэд дэвсгэр хэлхээг ашиглаарай.

    Android нь функцийг арын дэвсгэр рүү шилжүүлэх хэд хэдэн механизмаар хангадаг.

    • Activity.runOnUiThread(Ажиллуулах боломжтой)
    • View.post(Ажиллуулах боломжтой)
    • View.postDelayed(Ажиллуулах боломжтой, урт)
    • Ажиллагчид
    • AsyncTask

    AsyncTask-ийг ашиглах нь маш сайн шийдэл боловч цаана нь ажиллахын тулд өөрийн хэлхээ үүсгэж, удирдах шаардлагатай үе байдаг.

    Java нь дараах байдлаар ашиглаж болох стандарт ангитай:

    New Thread(new Runnable() ( public void run() ( //цаг хугацаа шаардсан үйлдлүүд хийх )); ) )).start();

    Энэ арга нь зөвхөн цаг хугацаатай холбоотой үйлдлүүдэд тохиромжтой. Гэхдээ та програмын GUI-г шинэчлэх боломжгүй.

    Хэрэв та програмын интерфейсийг шинэчлэх шаардлагатай бол ашиглах хэрэгтэй AsyncTask, дээр дурдсанчлан, эсвэл та объектыг ашиглахаас өвлөн авсан өөрийн классыг хэрэгжүүлж болно зохицуулагчбагцаас android.os UI-г шинэчлэхээс өмнө GUI урсгалтай синхрончлох.

    Та ангийн тусламжтайгаар хүүхдийн хэлхээ үүсгэж, удирдах боломжтой зохицуулагч, түүнчлэн нэрийн талбарт байгаа ангиуд java.lang. Thread. Үйлдлүүдийг хүүхэд урсгал руу түлхэх энгийн хүрээг доор харуулав.

    // Энэ аргыг үндсэн GUI урсгалаас дууддаг. private void mainProcessing() ( // Энд, цаг хугацаа шаардсан ажлуудыг хүүхэд урсгал руу шилжүүлдэг. Thread thread = new Thread(null, doBackgroundThreadProcessing, "Background"); thread.start(); ) // Ажиллаж болох объект даалгаврыг гүйцэтгэх арга / / далд. private Runnable doBackgroundThreadProcessing = new Runnable() ( public void run() ( backgroundThreadProcessing(); ) ); // Цаана нь зарим үйлдлийг гүйцэтгэдэг арга. private void backgroundThreadProcessing() ( [ ... Цаг хугацаа шаардсан үйлдлүүд... ] )

    Муу програм

    Үндсэн thread-ыг буруу ашигласан "муу" програм бичье. Нэг удаа бид хэрээ тоолох программ бичиж байлаа. Энэ удаад бид зам хөндлөн гарч буй хар муурыг тоолох болно. Тэд яагаад үүнийг хийдэг вэ - шинжлэх ухаан чимээгүй байна. Магадгүй цуглуулсан статистик нь нууцыг тайлахад тусална. Үйл ажиллагааны дэлгэцэнд товчлуур болон бичвэрийн шошго нэмье. Товч товших код.

    Нийтийн хүчингүй болгох onClick(Харах харагдац) ( long endTime = System.currentTimeMillis() + 20 * 1000; байхад (System.currentTimeMillis()< endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); }

    Хүнд хөдөлмөрийг дуурайхын тулд програм хорин секундын турш түр зогсоод, дараа нь муурны тоогоор текстийг харуулна. Хэрэв та товчлуурыг нэг удаа дараад хорин секунд хүлээх юм бол програм санаснаар ажиллах болно. Гэхдээ та товчлуурыг нэг удаа дарсан гэж төсөөлөөд үз дээ. Хөтөлбөр түр зогссон. Та завсарлага дуусахыг хүлээлгүй дахин товчлуурыг дарав. Хөтөлбөр нь таны тушаалыг гүйцэтгэх ёстой боловч өмнөх команд хараахан дуусаагүй байгаа тул зөрчил гарлаа. Богино завсарлагатайгаар товчлуурыг хэд хэдэн удаа дарж үзээрэй. Хэзээ нэгэн цагт програм царцаж, системийн харилцах цонхыг харуулах болно:

    AT бодит програмуудИйм цонх нь хэрэглэгчийг уурлуулах бөгөөд тэр таны програмд ​​бага үнэлгээ өгөх болно.

    Энэ тохиолдолд алдаа нь текстийн шошгон дээрх текстийн гаралтаас биш, дашрамд хэлэхэд үндсэн хэлхээнд хийгддэг, харин товчлуур дээр дарснаар үүсдэг. Хэрэв та холбоотой кодын сүүлийн хоёр мөрийг тайлбарлавал текст харах, дараа нь алдаа гарсаар байна.

    Та цаг хугацаа шаардсан ажлыг тусдаа хэлхээ рүү шилжүүлэх хэрэгтэй. Үүнийг хийхийн тулд тухайн ангийн жишээг үүсгэнэ гүйх боломжтойаргатай ажиллуулах(). Дараа нь тухайн объектыг үүсгэгч нь үүсгэсэн байна гүйх боломжтой. Үүний дараа та аргыг ашиглан шинэ хэлхээ үүсгэж болно эхлэх(). Жишээг дахин бичье.

    Public void onClick(Харах харагдац) ( Runnable runnable = new Runnable() ( public void run() ( // Хуучин кодыг энд зөөж урт endTime = System.currentTimeMillis() + 20 * 1000; while (System.currentTimeMillis()< endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } Log.i("Thread", "Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); // Нельзя! // TextView infoTextView = // (TextView) findViewById(R.id.textViewInfo); // infoTextView.setText("Сегодня коты перебегали дорогу: " + mCounter++ + " раз"); } }; Thread thread = new Thread(runnable); thread.start(); }

    Бид бүх кодыг арга руу шилжүүлсэн ажиллуулах(). Одоо та товчлуур дээр зогсолтгүй дарж болно. Энэ удаад аппликешн нь үйл ажиллагаагаа үргэлжлүүлэх болно. Үүнийг баталгаажуулахын тулд кодонд бүртгэлийг нэмсэн log.i(). Дарах бүр нь кодыг гүйцэтгэх шинэ хэлхээ үүсгэдэг. Threads нь бие биендээ саад болохгүй бөгөөд систем нь ажиллахыг зөвшөөрөх үед ээлжээ хүлээнэ.

    Үндсэн хэлхээг мөн UI thread гэж нэрлэдэг. Үндсэн хэлхээс дэх нэр, та текст шошгоны текстийг шинэчлэх боломжтой. Бидний үүсгэсэн урсгалуудад үүнийг хийх боломжгүй. Хэрэв та сүүлийн жишээний тайлбарыг арилгаад төслийг ажиллуулбал алдааны мэдэгдэл хүлээн авах болно.

    Бидэнд үүсгэсэн хэлхээнүүд болон үндсэн UI хэлхээний хооронд зуучлагч хэрэгтэй. Анги нь ийм зуучлагчийн үүрэг гүйцэтгэдэг. зохицуулагч(ангийн бүтэн нэр) android.os.Handler, андуурч болохгүй). Та ангийн жишээг үүсгэж, гүйцэтгэх кодыг зааж өгөх хэрэгтэй.

    Handler handler = new Handler() ( @Override public void handleMessage(Message msg) ( TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText("Муурууд өнөөдөр зам хөндлөн гарсан: " + mCounter++ + " удаа " );)))

    -тэй кодын мөрийн дараа log.i()зуучлагчийн аргад дуудлага нэмнэ.

    Log.i("Tread", "Өнөөдөр муурнууд зам хөндлөн гарлаа: " + mCounter++ + " times"); handler.sendEmptyMessage(0); // Хориотой! // TextView infoTextView = // (TextView) findViewById(R.id.textViewInfo); // infoTextView.setText("Өнөөдөр муурнууд зам хөндлөн гарлаа: " + mCounter++ + "удаа");

    Thread нь прокси-г дууддаг бөгөөд энэ нь эргээд интерфэйсийг шинэчилдэг. Манай тохиолдолд зуучлагч утаснаас хоосон мессеж илгээдэг.

    Гэхдээ утас боловсруулахын тулд мэдээлэл авах шаардлагатай болдог. Доорх нь хялбаршуулсан жишээ юм.

    Нийтийн хүчингүй болгох onClick(Харах харагдац) ( Ажиллуулах боломжтой ажиллуулах = шинэ Ажиллуулах() ( нийтийн хүчингүй ажиллуулах() ( Зурвас мессеж = handler.obtainMessage(); Багцын багц = шинэ Багц(); SimpleDateFormat dateFormat = шинэ SimpleDateFormat("HH:mm: ss MM/dd/yyyy", Locale.US); String dateString = dateFormat.format(new Date()); bundle.putString("Түлхүүр", dateString); msg.setData(багц); handler.sendMessage(msg) ; ) ); Thread thread = new Thread(ажилах боломжтой); thread.start(); ) Handler handler = new Handler()( @Override public void handleMessage(Message msg) ( Bundle bundle = msg.getData(); String date = bundle.getString("Түлхүүр"); TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText(огноо); ) );

    Сэдэв эхлүүлж байна

    Бид өөрсдийн тоглогчоо хөгжүүлж байна гэж бодъё. Бидэнд товчлуур байна тоглохаргыг дууддаг тоглох()хөгжим тоглох:

    Button playButton = (Товч) findViewById(R.id.play); playButton.setOnClickListener(шинэ View.OnClickListener()) ( нийтийн хүчингүй onClick(View v) ( тоглуулах(); // дуудах тоглуулах ) )

    Одоо өөр thread дээр аргыг ажиллуулъя. Эхлээд шинэ хэлхээ үүсгэнэ. Дараахь зүйлд объектыг тайлбарлав гүйх боломжтойурсгал үүсгэгч дотор. Мөн үүсгэсэн утаснуудын дотор бид өөрсдийн аргыг дууддаг тоглох(). Эцэст нь бид сэдвийг эхлүүлнэ.

    Thread myThread = new Thread(// шинэ хэлхээ үүсгэх new Runnable() ( // runnable объектыг бүтээгч public void run() дотор зарлах ( play(); // тоглох аргыг дуудах ) ));

    урсгалыг намжаах

    Заримдаа утсыг түр зогсоох шаардлагатай болдог ("унтуулах"):

    // 2 секунд унтах (миллисекундээр) myThread.sleep(2000);

    Thread Priority

    Процессын тэргүүлэх чиглэлийг тогтоохын тулд аргыг ашиглана уу setPriority(), энэ нь утас эхлэхээс өмнө дуудагддаг. Тэргүүлэх утга нь Thread.MIN_PRIORITY (1)-аас Thread.MAX_PRIORITY (10) хооронд хэлбэлзэж болно:

    MyThread.setPriority(10); myThread.start();

    Урсгалын гүйцэтгэлийг цуцлах

    Утас нь аргатай Зогс(), гэхдээ энэ нь програмыг тодорхойгүй төлөвт үлдээдэг тул ашиглахыг зөвлөдөггүй. Энэ аргыг ихэвчлэн ашигладаг:

    Хэрэв (myThread != null) ( Thread дамми = myThread; myThread = null; dummy.interrupt(); )

    Бүх ажиллаж байгаа хэлхээг демон гэж зарлах өөр нэг арга бий. Энэ тохиолдолд програмын үндсэн хэлхээ дуусах үед бүх ажиллаж байгаа хэлхээнүүд автоматаар дуусгавар болно:

    MyThread.setDaemon(үнэн); myThread.start();

    Би програмдаа ачаалах дэлгэцтэй болохын тулд энэ гарын авлагыг дагаж байна. AT сургалтын гарын авлагаЭнэ нь миний үйл ажиллагаа Sleep() командын хамт Sleep() байх ёстой гэсэн боловч энэ нь Sleep() функцийг функц гэж танихгүй бөгөөд намайг Sleep() аргыг үүсгэх эсэхийг асуухад алдаа гаргаж байна.

    http://androidcookbook.com/Recipe.seam;jsessionid=4DBCC1688B51DB16A2A40A86E135D361?recipeId=1599

    Энд жишээ код байна:

    Нийтийн анги LoadingScreenActivity өргөтгөл үйл ажиллагаа ( //Хувийн саатал эцсийн int WAIT_TIME = 2500; @Override protected void onCreate(Bundle savedInstanceState) ( // TODO Автоматаар үүсгэгдсэн арга stub super.onCreate(savedInstanceState); System.out.println(" LoadingScreenActivity дэлгэц эхэлсэн"); setContentView(R.layout.loading_screen); findViewById(R.id.mainSpinner1).setVisibility(View.VISIBLE); new Handler().postDelayed(new Runnable()( @Override public void run() ( //Удаан ажиллаж байгаа ажлыг дуурайж байна this.Sleep(1000); System.out.println("Профайлын өгөгдөл рүү очих"); /* ProfileData-Үйл ажиллагааг эхлүүлэх зорилго үүсгэ. */ Intent mainIntent = new Intent( LoadingScreenActivity.this,ProfileData.class); LoadingScreenActivity.this.startActivity(mainIntent); LoadingScreenActivity.this.finish(); ) ), WAIT_TIME); ) )

    Та дараах аргуудын аль нэгийг ашиглаж болно.

    Thread.sleep(timeInMills);

    Эсвэл

    SystemClock.sleep(timeInMills);

    SystemClock.sleep(миллисекунд) нь Thread.sleep(миллисекунд) -тай тун төстэй хэрэглүүрийн функц боловч InterruptedException-г үл тоомсорлодог. Хэрэв та Thread.interrupt()-г ашиглаагүй бол энэ функцийг саатуулахад ашиглаарай, учир нь энэ нь хэлхээний тасалдсан төлөвийг хадгалах болно.

    Уг функц нь Thread.sleep(long) юм.

    Гэхдээ та UI утсан дээр унтаж болохгүй гэдгийг анхаарна уу.

    Хэрэв та Handlers ашиглаж байгаа бол зохицуулагчийг үүсгэсэн гэдгийг анхаарна уу ажиллаж байгаа утас дээр . Тиймээс UI thread дээр new Handler().post(...)-г дуудах нь "удаан ажиллаж байгаа үйлдлийг" багтаасан UI thread дээр ажиллах боломжтойг гүйцэтгэх болно. Давуу тал нь та UI thread-д ашиглах боломжтой зохицуулагч үүсгэх боломжтой юм. Дараа нь доор үзүүлсэн шиг.

    Арын урсгал дээр удаан ажиллаж байгаа үйлдлийг оруулахын тулд та доор үзүүлсэн шиг гүйлгээний эргэн тойронд утас үүсгэх хэрэгтэй. Одоо, хэрэв та удаан ажиллаж дууссаны дараа UI-г шинэчлэхийг хүсвэл үүнийг зохицуулагчийн тусламжтайгаар UI хэлхээнд нийтлэх хэрэгтэй.

    Энэ функц нь AsyncTask-д төгс тохирох бөгөөд энэ нь доорх загвараас хамаагүй цэвэрхэн харагдах болно гэдгийг анхаарна уу. Гэсэн хэдий ч, боловсруулагч, урсгал болон удирддаг файлууд хэрхэн холбоотой болохыг харуулахын тулд би үүнийг оруулсан.

    Нийтийн анги LoadingScreenActivity өргөтгөл үйл ажиллагаа ( //Хувийн эцсийн int WAIT_TIME = 2500 саатал нэвтрүүлэх; private Handler uiHandler; @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); uiHandler = ямар нэгэн зүйл нийтэлсэн // шинэ Handler(); Энэ зохицуулагч нь UI Thread System дээр ажиллах болно.out.println("LoadingScreenActivity дэлгэц эхэлсэн"); setContentView(R.layout.loading_screen); findViewById(R.id.mainSpinner1).setVisibility(View.VISIBLE); Runnable onUi = new Runnable() ( @Override public void run() ( // энэ нь үндсэн UI урсгал дээр ажиллах болно Intent mainIntent = new Intent(LoadingScreenActivity.this,ProfileData.class); LoadingScreenActivity.this.startActivity(mainIntent); LoadingScreenActivity.this .finish(); ) ); Ажиллаж болох дэвсгэр = new Runnable() ( @Override public void run() ( // Энэ бол Thread.Sleep(WAIT_TIME) саатал юм); // Энэ нь дэвсгэр урсгал дээр ажиллана //Симуляци хийх Урт хугацааны даалгавар Thread.Sleep(1000);System.out.println("P руу явж байна. rofile Data"); uiHandler.post(onUi); ) ); new Thread(background).start(); )

    Thread.sleep() аргыг миллисекундээр тодорхой хугацаанд одоогийн урсгалын гүйцэтгэлийг түр зогсооход ашиглаж болно. Аргументийн миллисекундын утга сөрөг байж болохгүй, эс тэгвээс энэ нь IllegalArgumentException-г шиднэ.

    Одоогийн хэлхээний гүйцэтгэлийг заасан миллисекунд болон наносекундэд түр зогсооход ашиглаж болох өөр унтах (урт миллис, инт нанос) арга байдаг. Хүчинтэй нано секундын утга нь 0-ээс 999999 хооронд байна.

    Хэрэв ямар нэгэн хэлхээ одоогийн урсгалыг тасалдуулсан бол InterruptedException шидэгддэг. Энэ үл хамаарах зүйл тохиолдоход одоогийн хэлхээний тасалдсан төлөв арилна.

    Зар:

    Нийтийн статик хүчингүй нойр (урт милли) нь InterruptedException-г шиддэг

    Thread Sleep хэрхэн ажилладаг вэ?

    Thread.sleep() нь урсгалын хуваарьлагчтай харилцаж, одоогийн хэлхээг заасан хугацаанд унтуулах горимд оруулдаг. Хүлээлтийн хугацаа өнгөрөхөд урсгалын төлөв ажиллах боломжтой төлөвт шилжиж, CPU цаашид ажиллахыг хүлээнэ.

    Тиймээс одоогийн урсгалын бодит хүлээх хугацаа нь үйлдлийн системийн нэг хэсэг болох thread төлөвлөгчөөс хамаарна.

    Java хэл дээрх утас унтах жишээ

    Энд Thread.sleep() нь үндсэн хэлхээг 2 секундээр дуусгахад ашиглагддаг.

    com.journaldev.threads багц; public class ThreadSleep ( public static void main(String args) нь InterruptedException-ыг шиддэг ( урт эхлэл = System.currentTimeMillis(); Thread.sleep(2000); System.out.println("Унтах хугацаа ms = "+(System.currentTimeMillis() )-эхлэх))) )))

    Хэрэв та энэ программыг ажиллуулбал түүний хэвлэх урсгалын хугацаа 2000-аас арай урт байгааг анзаарах болно. Энэ нь thread-ийн хүлээх горимын ажил болон үйлдлийн систем дэх thread төлөвлөгчийн тодорхой хэрэгжилтээс шалтгаална.

    Үүнийг мэдэх нь чухал

    • Одоогийн хэлхээний гүйцэтгэлийг үргэлж түр зогсоодог.
    • Бодит утас нь сэрэхээсээ өмнө "унтдаг" бөгөөд гүйцэтгэлийн хугацаа нь системийн таймер болон төлөвлөгчөөс хамаарна.
    • Унтаж буй утас нь одоогийн утсыг блоклодоггүй.
    • Бусад ямар ч урсгал нь унтаж байх үед одоогийн урсгалыг тасалдуулж болох бөгөөд энэ тохиолдолд InterruptedException шидэгддэг.

    Java.lang.Thread.sleep() аргыг ашигласан өөр нэг жишээ.

    com.tutorial багц; java.lang.* импортлох; нийтийн анги ThreadDemo нь Runnable-г хэрэгжүүлдэг ( Thread t; public void run() ( for (int i = 10; i)

    Програмаа эмхэтгэж ажиллуулъя, энэ нь дараах үр дүнг өгнө.
    утас - 0 10
    утас-1 10
    Сэдэв-0 11
    утас-1 11
    Сэдэв-0 12
    утас-1 12

    Нийтлэлд үнэлгээ өгнө үү

    Тооцоолох

    Бүтээж байхдаа гар утасны програмарай илүү төвөгтэй "Сайн уу, ертөнц" нь вэбээс ямар нэгэн зүйл татаж авах эсвэл дискнээс файл уншихыг шаарддаг. Програмыг бүхэлд нь тогтвортой ажиллуулахын тулд эдгээр үйлдлүүдийг тусдаа хэлхээнд хийх ёстой. Яагаад, хэзээ, хэрхэн Android дээр шинэ хэлхээ үүсгэх вэ - та энэ нийтлэлээс энэ талаар мэдэх болно.

    Процесс ба утаснууд

    Android API-тай ажиллахаасаа өмнө энэ үйлдлийн систем ямар бүтэцтэй болохыг санацгаая. Энэ нь бүх * nix системд байдаг үндсэн механизмуудыг хэрэгжүүлдэг Линуксийн цөм дээр суурилдаг. Цөм нь доод түвшний ажилд зориулагдсан модулиудыг агуулдаг: техник хангамжтай харилцах, санах ойн зохион байгуулалт, файлын систем гэх мэт.

    Линуксийн ертөнцөд ажиллаж байгаа програм бүр тусдаа байдаг үйл явц. Процесс бүр нь өвөрмөц дугаартай бөгөөд өөрийн "нутаг дэвсгэр" - үйл явцын бүх өгөгдлийг агуулсан виртуал хаягийн орон зай юм. УрсгалЭнэ нь тус тусад нь гүйцэтгэх боломжтой ажиллаж байгаа программ (процесс) доторх заавруудын багц юм. Thread нь өөрийн өвөрмөц танигч, хаягийн орон зайгүй - энэ бүгдийг эх процессоос өвлөн авч бусад хэлхээнүүдтэй хуваалцдаг.

    Google Play дээр санах ой алдагдсантай холбоотой програмуудыг олноор нь түгээх нь хэрэглэгчдэд "Андройд удаан" гэсэн сэтгэгдэл төрүүлэх болно.

    Энэхүү нөхцөл байдал нь гаднаас нь харахад үйл явцын дотор амьдрал хэрхэн явагддаг, утаснууд байгаа эсэх, хичнээн олон байдаг нь мэдэгдэхгүй байгаа нь OS болон бусад процессуудын хувьд энэ нь өвөрмөц танигчтай атомын бүтэц юм. Тиймээс үйлдлийн систем нь зөвхөн процессыг удирдах боломжтой бөгөөд зөвхөн тэдгээрийг үүсгэсэн процесс нь хэлхээг удирддаг. Ерөнхийдөө, дотоод ертөнц үйлдлийн системүүдмаш сонирхолтой тул уншигчдад Линукс дээрх сонгодог уран зохиолоос ямар нэг зүйлийг уншихыг зөвлөж байна.

    Олон цөмтэй процессорууд компьютерт (мөн тэдгээрийн дараа таблет, утсанд) гарч ирэхэд програмистууд үйлдлийн системд даалгавар төлөвлөгчийг нэвтрүүлсэн. Ийм хуваарь гаргагч нь процессорын бүх цөмд ачааллыг бие даан хуваарилж, кодын блокуудыг зэрэгцээ эсвэл асинхроноор гүйцэтгэдэг бөгөөд ингэснээр гүйцэтгэлийг сайжруулдаг. Эхэндээ маркетерууд "Хоёр цөм - хоёр дахин хурдан" гэсэн уриатай компьютер зардаг байсан ч харамсалтай нь энэ нь бодит байдалтай нийцэхгүй байна.

    Андройд дээр бүх газар шинэ хэлхээ, процесс үүсгэх нь програмистын үүрэг юм. Хэдэн секундээс илүү үргэлжилж болох бүх үйлдлүүдийг тусдаа урсгал дээр гүйцэтгэх ёстой. Үгүй бол интерфэйсийг үзүүлэхэд саатал гарах бөгөөд хэрэглэгч програм "царцах" мэт санагдах болно.

    Ерөнхийдөө олон урсгалтай програмчлалын мөн чанар нь тооцооллын үр дүнг синхрончлохын зэрэгцээ төхөөрөмжийн бүх нөөцийг аль болох ашиглах явдал юм. Энэ нь эхлээд харахад тийм ч хялбар биш боловч Android-ийг бүтээгчид API-д Java хөгжүүлэгчийн амьдралыг ихээхэн хялбаршуулсан хэд хэдэн ашигтай ангиудыг нэмсэн.

    Android дээрх Threads

    Андройд дээр ажилладаг програм нь өөрийн гэсэн процесстой бөгөөд дор хаяж нэг урсгалтай байдаг - үндсэн урсгал гэж нэрлэгддэг. Хэрэв програм нь харааны элементүүдтэй бол энэ хэлхээнд Activity ангиллын объектыг эхлүүлсэн бөгөөд энэ нь интерфэйсийг (хэрэглэгчийн интерфейс, UI) дэлгэц дээр зурах үүрэгтэй.

    Үндсэн үйл ажиллагаа нь аль болох бага тооцоололтой байх ёстой бөгөөд түүний цорын ганц даалгавар бол UI-г харуулах явдал юм. Хэрэв үндсэн хэлхээ нь pi тоог тоолох завгүй байвал хэрэглэгчтэй холбоо тасрах болно - тоо тоологдох хүртэл Үйл ажиллагаа нь хэрэглэгчийн хүсэлтийг боловсруулах боломжгүй бөгөөд гаднаас нь програм өлгөгдсөн мэт харагдах болно. Хэрэв хүлээх хугацаа хэдхэн секундээс илүү үргэлжилбэл Android үйлдлийн систем үүнийг анзаарах бөгөөд хэрэглэгч програмыг хүчингүй болгох санал бүхий ANR (програм хариу өгөхгүй байна) мессежийг харах болно.


    Ийм мессежийг хүлээн авах нь тийм ч хэцүү биш - үндсэн хэлхээнд файлын систем, сүлжээ, криптограф зэрэгтэй ажиллахад хангалттай. Таны ойлгож байгаагаар энэ нь програмын ердийн горимд давтагдах ёсгүй маш муу нөхцөл байдал юм.

    Thread болон Runnable

    Android дахь thread-ийн үндсэн анги нь Thread класс бөгөөд thread үүсгэхэд бэлэн байдаг. Гэхдээ шинэ thread дотор ямар нэгэн зүйл хийхийн тулд та өгөгдлийг Runnable ангийн объектод оруулах хэрэгтэй. Thread нь энэ ангийн объектыг хүлээн авсны дараа шууд ажиллуулах аргыг гүйцэтгэх болно.

    Нийтийн анги MyRunnable хэрэгжүүлдэг Runnable ( String goal; public MyRunnable(String goal) ( this.goal=goal; ) @Override public void run() ( getData(goal); ) ) ... MyRunnable runnable = new MyRunnable("do_smth" ); new Thread(гүйлгэх боломжтой).start();

    Гэхдээ ийм зохион байгуулалттай бол нэмэлт утаснуудын хүчийг бүрэн ашиглахад хэцүү байдаг - та даалгавраа өөрчлөх, тооцооллын үр дүнг харах боломжгүй. Хэдийгээр энэ бүхэн нэг хаягийн орон зайд тохиолддог ч Java хөгжүүлэгч хөрш зэргэлдээх хэлхээнүүдийн нөөцийг олж авах арга байхгүй.

    гогцоо

    Нэг урсгалаас нөгөө рүү өгөгдөл дамжуулах боломжтой байх нь сайхан байх болно. Ямар ч Линукс системийн нэгэн адил Android дээр энэ нь боломжтой. Android дээр ашиглах боломжтой аргуудын нэг нь мессежийн дараалал үүсгэх(MessageQueue) хэлхээ доторх. Бусад хэлхээний ажлыг ийм дараалалд нэмж болно; ажил нь хувьсагч, объект эсвэл гүйцэтгэх код (Runnable) байж болно.

    Message msg = new Message(); Багц mBundle = шинэ Багц(); mBundle.putString("KEY", "textMessage"); msg.setData(mBundle);

    Дараалалыг зохион байгуулахын тулд та Handler болон Looper ангиудыг ашиглах хэрэгтэй: эхнийх нь дарааллыг зохион байгуулах үүрэгтэй, хоёр дахь нь төгсгөлгүй давталтаар түүн доторх хэлхээнд шинэ даалгавар байгаа эсэхийг шалгадаг.

    Нийтийн анги MyLooper Thread-ыг сунгана ( Бүхэл тоо; нийтийн Handler mHandler; @Override public void run() ( Looper.prepare(); mHandler = new Handler() ( @Override public void handleMessage(Message msg) ( // энд ирж буй мессежийг боловсруулна. Log.e("Tread", "#"+number + ": "+msg.getData().getString("KEY")); ) ); Looper.loop(); ) )

    Ийм хэлхээг эхлүүлэх нь ижил төстэй загварыг дагаж мөрддөг - шинэ объект үүсгэж, эхлүүлэх аргыг дууддаг.

    MyLooper myLooper = шинэ MyLooper(); myLooper.start();

    Энэ аргыг хэрэгжүүлсний дараа шинэ утас үүсэх бөгөөд энэ нь өөрөө амьдрах болно. Энэ нь хувьсагчдыг эхлүүлэх, объект үүсгэх нь myLooper.start() командын дараа дараах мөрөнд бөглөрсөн дуудлагатай зэрэгцэн явагдана гэсэн үг юм. Тиймээс, шинэ хэлхээний дараалалд хандахын өмнө та жаахан хүлээх хэрэгтэй - зохицуулагч объект хараахан байхгүй байж магадгүй юм.

    Хэрэв (myLooper.hanlder!=null) ( myLooper.mHandler.sendMessage(msg); )

    AsynkTask

    Цаана нь ямар нэг зүйлийг ачаалах, тооцоолохдоо зөвхөн үр дүнд хүрэхээс гадна явцын мэдээллийг хэрэглэгчдэд харуулах боломжтой байх нь сайхан байх болно. Мэдээжийн хэрэг, та мессежийн дарааллыг ашиглан энэ бүгдийг өөрөө хийж болно, гэхдээ Android хөгжүүлэгчид AsyncTask анги үүсгэснээр бидний амьдралыг хөнгөвчилсөн.

    Үргэлжлүүлэн зөвхөн гишүүдэд ашиглах боломжтой

    Сонголт 1. Сайт дээрх бүх материалыг уншихын тулд "сайт" нийгэмлэгт нэгдээрэй

    Тодорхой хугацаанд нийгэмлэгт гишүүнээр элссэнээр Хакерын БҮХ материалд хандах, хувийн хадгаламжийн хөнгөлөлтийг нэмэгдүүлэх, хуримтлуулах боломжийг олгоно. мэргэжлийн үнэлгээ Xakep оноо!

    airsoft-unity.ru - Уул уурхайн портал - Бизнесийн төрлүүд. Зааварчилгаа. Компаниуд. Маркетинг. татвар