Android অ্যাপ ফ্রেমওয়ার্ক UI হল অবজেক্টের একটি হায়ারার্কির উপর ভিত্তি করে তৈরি হয় যা View দিয়ে শুরু হয়। সব UI এলিমেন্টকে একাধিকবার পরিমাপ করা হয় এবং লেআউট প্রসেসের মাধ্যমে সেগুলিকে আয়তাকার জায়গায় ফিট করা হয়। তারপরে, অ্যাপটি ফোরগ্রাউন্ডে আনা হলে, WindowManager-এর সেট-আপ করা সারফেসে ফ্রেমওয়ার্ক সবকটি দৃশ্যমান ভিউ অবজেক্ট রেন্ডার করে। অ্যাপের UI থ্রেড ফ্রেম প্রতি বাফারে লেআউট এবং রেন্ডারিং পারফর্ম করে।
SurfaceView
SurfaceView হল এমন একটি কম্পোনেন্ট যা আপনি নিজের ভিউ হায়ারার্কির মধ্যে একটি অতিরিক্ত কম্পোজিট লেয়ার এম্বেড করতে ব্যবহার করতে পারেন। SurfaceView অন্যান্য ভিউয়ের মতো একই লেআউট প্যারামিটার নেয়, তাই এটিকে অন্য যেকোনও ভিউয়ের মতো ম্যানিপুলেট করা যায়, কিন্তু SurfaceView-এর কন্টেন্ট ট্রান্সপারেন্ট হয়।
GL কনটেক্সট বা মিডিয়া ডিকোডারের মতো এক্সটার্নাল বাফার সোর্স দিয়ে রেন্ডার করার সময়, স্ক্রিনে বাফার দেখানোর জন্য আপনাকে বাফার সোর্স থেকে বাফার কপি করতে হবে। SurfaceView ব্যবহার করে আপনি এটি করতে পারবেন।
SurfaceView-এর ভিউ কম্পোনেন্ট দৃশ্যমান হওয়ার ঠিক আগে, ফ্রেমওয়ার্ক SurfaceControl-কে SurfaceFlinger থেকে নতুন সারফেসের অনুরোধ করতে বলে। সারফেস তৈরি বা ধ্বংস করা হলে কলব্যাক পেতে, SurfaceHolder ইন্টারফেস ব্যবহার করুন। ডিফল্ট হিসেবে, ফ্রেমওয়ার্ক নতুন তৈরি করা সারফেসকে অ্যাপ UI সারফেসের পিছনে প্লেস করে। নতুন সারফেস উপরে রাখতে আপনি ডিফল্ট Z-অর্ডারিং ওভাররাইড করতে পারবেন।
SurfaceView-এর মাধ্যমে রেন্ডার করা সেইসব ক্ষেত্রে উপকারী যেখানে আপনাকে আলাদা সারফেসে রেন্ডার করতে হয়, যেমন Camera API বা OpenGL ES কনটেক্সটের মাধ্যমে রেন্ডার করার সময়। SurfaceView-এর মাধ্যমে রেন্ডার করার সময়, SurfaceFlinger সরাসরি স্ক্রিনে বাফার কম্পোজ করে। SurfaceView ছাড়া, আপনাকে অফস্ক্রিন সারফেসে বাফার কম্পোজিট করতে হবে, যা পরে স্ক্রিনে কম্পোজিট করা হয়, তাই SurfaceView-এর মাধ্যমে রেন্ডার করলে অতিরিক্ত কাজ করতে হয় না। SurfaceView-এর মাধ্যমে রেন্ডার করার পরে, অ্যাক্টিভিটি লাইফসাইকেলের সাথে সমন্বয় করতে UI থ্রেড ব্যবহার করুন এবং প্রয়োজন হলে ভিউয়ের সাইজ বা পজিশন অ্যাডজাস্ট করুন। তারপরে, হার্ডওয়্যার কম্পোজার অ্যাপ UI ও অন্যান্য লেয়ারকে মিশিয়ে দেয়।
নতুন সারফেস হল BufferQueue-এর প্রযোজক সাইড, যার গ্রাহক হল SurfaceFlinger লেয়ার। আপনি এমন যেকোনও মেকানিজমের মাধ্যমে সারফেস আপডেট করতে পারবেন যা BufferQueue-তে ফিড করতে পারে, যেমন সারফেস-সাপ্লাইড Canvas ফাংশন, একটি EGLSurface অ্যাটাচ করা এবং GLES-এর মাধ্যমে সারফেসে আঁকা অথবা সারফেস লেখার জন্য একটি মিডিয়া ডিকোডার কনফিগার করা।
SurfaceView এবং অ্যাক্টিভিটি লাইফসাইকেল
SurfaceView ব্যবহার করার সময়, মূল UI থ্রেড ছাড়া অন্য কোনও থ্রেড থেকে সারফেস রেন্ডার করুন।
SurfaceView সহ কোনও অ্যাক্টিভিটির জন্য, দুটি আলাদা কিন্তু একে অপরের উপর নির্ভরশীল স্টেট মেশিন আছে:
- অ্যাপ
onCreate/onResume/onPause - সারফেস তৈরি/পরিবর্তন/ধ্বংস করা হয়েছে
অ্যাক্টিভিটি শুরু হলে, আপনি এই ক্রমে কলব্যাক পাবেন:
onCreate()onResume()surfaceCreated()surfaceChanged()
আপনি 'ফিরে যান' বোতামে ক্লিক করলে, এগুলি পাবেন:
onPause()surfaceDestroyed()(সারফেস বন্ধ হওয়ার ঠিক আগে কল করা হয়)
আপনি স্ক্রিন রোটেট করলে, অ্যাক্টিভিটি বন্ধ হয়ে আবার তৈরি হয় এবং আপনি
সম্পূর্ণ সাইকেল পান। isFinishing() চেক করে এটি যে একটি দ্রুত রিস্টার্ট তা আপনি বুঝতে পারবেন।
কোনও অ্যাক্টিভিটি এত দ্রুত শুরু/বন্ধ করা সম্ভব
যে onPause()-এর পরে surfaceCreated() হয়।
স্ক্রিন ফাঁকা করতে পাওয়ার বোতামে ট্যাপ করলে, আপনি শুধু
onPause() পাবেন, surfaceDestroyed() নয়। সারফেস
অ্যাক্টিভ থাকে এবং রেন্ডারিং চলতে থাকে। আপনি অনুরোধ করা চালিয়ে গেলে, Choreographer ইভেন্ট পাওয়া চালিয়ে যেতে পারবেন। আপনার লক
স্ক্রিন যদি অন্য কোনও ওরিয়েন্টেশন প্রয়োগ করে, তাহলে ডিভাইস আনব্ল্যাঙ্ক করার সময় আপনার অ্যাক্টিভিটি
রিস্টার্ট হতে পারে। অন্যথায়, আপনি আগের মতো একই সারফেস সহ স্ক্রিন-ব্ল্যাঙ্ক থেকে বেরিয়ে আসতে পারবেন।
স্ক্রিন ফাঁকা হয়ে গেলে আপনি কী করতে চান তার উপর নির্ভর করে, থ্রেডের মেয়াদ সারফেস বা অ্যাক্টিভিটির সাথে যুক্ত থাকতে পারে। থ্রেড অ্যাক্টিভিটি শুরু/বন্ধ অথবা সারফেস তৈরি/ধ্বংসের সময় শুরু/বন্ধ হতে পারে।
অ্যাক্টিভিটি শুরু/বন্ধ হওয়ার সাথে সাথে থ্রেড শুরু/বন্ধ হলে তা অ্যাপের
লাইফসাইকেলের সাথে ভালভাবে কাজ করে। আপনি onResume()-এ রেন্ডারার থ্রেড শুরু করেন এবং
onStop()-এ এটি বন্ধ করেন। থ্রেড তৈরি ও কনফিগার করার সময়,
কখনও কখনও সারফেস আগে থেকেই থাকে, আবার কখনও থাকে না (যেমন,
পাওয়ার বোতাম দিয়ে স্ক্রিন টগল করার পরেও এটি অ্যাক্টিভ থাকে)। থ্রেডে শুরু করার আগে সারফেস তৈরি হওয়ার জন্য আপনাকে
অপেক্ষা করতে হবে। আপনি surfaceCreate() কলব্যাকে
ইনিশিয়ালাইজ করতে পারবেন না কারণ সারফেস আবার তৈরি না হলে এটি
আবার ফায়ার হবে না। পরিবর্তে, সারফেস
স্টেট কোয়েরি বা ক্যাশে করুন এবং এটি রেন্ডারার থ্রেডে ফরওয়ার্ড করুন।
সারফেস তৈরি/ধ্বংস করার সময় থ্রেড শুরু/বন্ধ করা ভালো কাজ করে কারণ
সারফেস ও রেন্ডারার একে অপরের সাথে যুক্ত। সারফেস তৈরি হওয়ার পরে আপনি থ্রেড শুরু করেন, যা কিছু ইন্টারথ্রেড কমিউনিকেশন
সংক্রান্ত সমস্যা এড়ায়; এবং সারফেস তৈরি/পরিবর্তন সংক্রান্ত মেসেজ ফরওয়ার্ড করা হয়। স্ক্রিন ফাঁকা হয়ে গেলে রেন্ডারিং বন্ধ হয়ে যায় এবং ফাঁকা অবস্থা সরে গেলে আবার শুরু হয় কিনা তা যাচাই করতে, ফ্রেম ড্র কলব্যাক ইনভোক করা বন্ধ করতে Choreographer-কে
বলুন। onResume()
রেন্ডারার থ্রেড চালু থাকলে কলব্যাক আবার শুরু করে। তবে, আপনি যদি
ফ্রেমের মধ্যে অতিবাহিত সময়ের উপর ভিত্তি করে অ্যানিমেট করেন, তাহলে
পরবর্তী ইভেন্ট আসার আগে একটি বড় ফাঁক থাকতে পারে; একটি স্পষ্ট পজ/রিজিউম মেসেজ ব্যবহার করে এই
সমস্যার সমাধান করা যেতে পারে।
থ্রেডের মেয়াদ অ্যাক্টিভিটি
বা সারফেসের সাথে যুক্ত থাকুক না কেন, দুটি বিকল্পই রেন্ডারার থ্রেড কীভাবে
কনফিগার করা হয়েছে এবং সেটি এক্সিকিউট হচ্ছে কিনা সেই বিষয়ে ফোকাস করে। অ্যাক্টিভিটি বন্ধ করা হলে (onStop() বা
onSaveInstanceState()) থ্রেড থেকে স্টেট
এক্সট্র্যাক্ট করা সংক্রান্ত একটি সমস্যা রয়েছে; এই ধরনের ক্ষেত্রে, অ্যাক্টিভিটির সাথে
থ্রেডের লাইফস্প্যান অ্যাটাচ করা সবচেয়ে ভাল কাজ করে কারণ
রেন্ডারার থ্রেড যোগ করার পরে, রেন্ডার করা থ্রেডের স্টেটকে
সিনক্রোনাইজেশন প্রিমিটিভ ছাড়াই অ্যাক্সেস করা যায়।
GLSurfaceView
GLSurfaceView ক্লাস EGL কনটেক্সট ম্যানেজ করা, ইন্টারথ্রেড কমিউনিকেশন এবং অ্যাক্টিভিটি লাইফসাইকেলের সাথে ইন্টার্যাকশনের জন্য হেল্পার ক্লাস প্রদান করে। GLES ব্যবহার করার জন্য আপনাকে GLSurfaceView ব্যবহার করতে হবে না।
যেমন, GLSurfaceView রেন্ডারিংয়ের জন্য একটি থ্রেড তৈরি করে এবং সেখানে একটি EGL কনটেক্সট কনফিগার করে। অ্যাক্টিভিটি পজ করা হলে, স্টেট অটোমেটিক ক্লিন-আপ করা হয়। GLSurfaceView-এর সাথে GLES ব্যবহার করার জন্য বেশিরভাগ অ্যাপকে EGL সম্পর্কে কিছু জানতে হয় না।
বেশিরভাগ ক্ষেত্রে, GLSurfaceView GLES ব্যবহার করে কাজ করাকে আরও সহজ করে তুলতে পারে। কিছু কিছু ক্ষেত্রে, এটি বাধা সৃষ্টি করতে পারে।