کیان
2 سال پیش توسط کیان مطرح شد
6 پاسخ

آقا گیج شدیم رفت - مشکل با paginate و هندل آن سمت اندروید

سلام به همه اساتید ممنون میشم با اینکه توضیحات طولانی میشه بخونید و راهنمایی کنید چون دیگه مغزم راه نمیده
برای شروع کامنت های اینستاگرام رو در نظر بگیرید که مثلا تعداد n ایتم رو از آخر به اول بر میگردونه و بعد n تا n تا جلو میره
خب من هم با این دستور سمت لاراول :


            $comment = ProfilePostComment::with('user:id,photo,user')
            ->where('post_id',$id)
                ->orderBy('id','DESC')
                ->paginate(10);

10 تا 10 تا از آخر اطلاعات رو میخونم
خب برای نمایش توی اندروید اومدم چکار کردم last page رو توی لاراول گرفتم و توی اندروید دریافت کردم یعنی مثلا فرض کنید 50 تا ایتم داریم میشه 10 تا آخر گرفته بشه و last page هم میشه 5 که اینطوری توی اندروید بار اول page 1 رو میفرستم و سکشن اول رو میگیرم و بعد هر بار که به آخر لیست(recyclerview) رفته میشه 1 دونه به count اضافه میکنم و سکشن بعد و الی آخر یعنی تا زمانیکه count مساوی last page بشه ادامه پیدا میکنه
خب تا اینجا همه چیز درست کار میکنه (البته این رو هم بگم این ترفند رو خودم زدم چون برای ساخت endless scroll در اندروید دیدم یه روش پیچیده دیگه استفاده میشه من خودم این کار رو انجام دادم)
در هر صورت همه چیز درست هست
حالا فکر کنید 10 تا ایتم اول کش شدن یعنی 50 تا 41
اگر کاربر بیاد یه دونه ایتم اضافه یا حذف کنه و من باید اون رو به جدول پاس بدم و اگر ریسپانس مثبت بود خودم دستی اون رو به لیست اضافه یا از لیست کم کنم در واقع صفحه رو دوباره رفرش نمیکنه (البته فکر کنم متوجه بشید چرا ... چون مثلا فکر کنید طرف توی page 10 هست اگر از اونجا یه دونه حذف کنه من بخوام دوباره صفحه رو رفرش کنم برمیگرده به صفحه اول و ایتم اول و هر چی لود شده میپره)
البته میشه صفحه رو رفرش کرد اما توی مثلا همون اینستا هم اینطوری نیست و میخوام ببینم چکار کرده که شده

حالا مشکل کجاست
فکر کنید ایتم 50 تا 41 لود شده یعنی page 1 اگر کاربر یه دونه به لیست اضافه کنه توی جدول یه دونه به پیچ 1 اضافه شده یعنی دیگه از 51 تا 42 هستش اما چون طبق روال قبل 50 تا 41 لود شه به جای اینکه از 40 تا 31 کش بشه چون یه دونه اضافه شده از 41 تا 32 کش میشه و اینطوری من دوبار 41 رو خواهم داشت و اگر تعداد اضافه ها بیشتر باشه همونقدر داستان دارم اگر هم که ایتم رو حذف کنم به همون تعداد که حذف کردم از ایتم ها میپره و skip میکنه که میدونم میدونید علتش چیه ... (همون داستان اضافه شدن هست یعنی 50 تا 41 بوده یه دونه حذف شده به جای اینکه 40 تا 31 بیاد 39 تا 30 برمیگرده و 41 میپره مثلا)

موندم چطوری این داستان رو هندل کنم و نکته اینکه نمیخوام صفحه رو رفرش کنم

ممنون میشم اگر چیز ی به ذهن تون میرسه راهنمایی کنید
سپاس و پوزش بابت طولانی شدن متن


ثبت پرسش جدید
محمدحسن یگانه
تخصص : Full-Stack Web Developer Freel...
@mhyeganeh 2 سال پیش آپدیت شد
0

سلام.
مسئله ای که باهاش مواجه شدید خیلی رایج هست و لاراول هم یک راه حل خیلی ساده و کلید طلایی براش داره بنام :
Cursor Pagination

$users = DB::table('users')->orderBy('id')->cursorPaginate(15);

حتما یک سری به اینجا بزنید و توضیحات کاملش رو مطالعه کنید. اما به طور خلاصه تفاوت cursor pagination با pagination های معمولی رو در کوئری هایی که می‌سازند می‌تونید ببینید:

# Offset Pagination...
select * from users order by id asc limit 15 offset 15;

# Cursor Pagination...
select * from users where id > 15 order by id asc limit 15;

کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش آپدیت شد
0

اساتید عزیز یه سوال برام پیش اومد
من اگر از skip و take استفاده کنم برای هندل این داستان مشکلی پیش میاد
مثلا :

            $comment = ProfilePostComment::with('user:id,photo,user')
                ->where('post_id', $id)
                ->orderBy('id', 'DESC')
                ->skip($request->skip)
                ->take($limit)
                ->get();

این رو در نظر بگیرید من بار اول بیام skip رو صفر پاس بدم و limit رو 10 خب 10 تای اول بر میگرده حالا بسته به اینکه چند تا رکورد توی لیست سمت اندرویدم هست (مثلا یکی اضافه شده یا یکی کم شده یا هر چیزی ) چک کنم ببینم چند تا ایتم وجود داره مثلا یکی حذف شده پس 9 تا وجود داره (توی اندروید میشه تعداد ایتم ها لیست رو به دست آورد) اینطوری همون تعداد رو به عنوان skip پاس بدم و limit هم که ثابت همون 10 تاست اینطوری 10 تا ایتم بعد از اون تعداد موجود توی لیستم درخواست داده میشه
فکر کنم عملی باشه فقط اینکه یه سوال برام پیش میاد اینکه اولا این کار درست و اصولی هست و اینکه نسبت به مدل paginate باری که روی سرور برای fetch کردن داده ها داره بیشتر نمیشه
ممنون میشم راهنمایی کنید سپاس


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش آپدیت شد
0

آقا ما این مدل skip هم رفتیم به خیال اینکه درست میشه و جالب اینه که شد یعنی مثلا همون کامنت ها رو در نظر بگیرید
خب من 10 تای اول رو فرستادم خودم یه کامنت میگذارم میشه 11 ایتم خب میخوام 10 تای بعدی بگیرم اوکی من 11 تا ایتم دارم تا اینجا پس 11 رو به عنوان skip میفرستم و از 11 به بعد 10 تا دیگه گرفته میشه و اوکی میشه و توی حذف هم همینطور

ولی باز یه مشکل دارم خب ممکنه همزمان با اضافه یا کم کردن من یک سری ایتم دیگه توسط دیگر کاربران توی جدول کم یا زیاد شدن اون موقع دوباره همه چیز بهم میریزه .... اووووووووف دیگه رد دادم خداییش

مثلا اپ دیوار رو در نظر بگیریم
خب من 10 تا ایتم اول رو کش کردم اوکی رسیدم اخر لیست 10 تا رو اسکیپ میکنم و از ایتم 11 به بعد 10 تا رو میگیرم یعنی میشه ایدی 11 تا 20 مثلا
اگر همین موقع 5 رکورد دیگه توسط دیگر کاربرها اضافه بشه خب من 10 تا رو اسکیپ میکنم و باید از ایدی 11 بگیره اما 5 تا اضافه شده پس از ایدی 15 میگیره
این چطوری میشه خب دوباره که قاتی پاتی شد
الان یعنی دیوار دقیقا چکار میکنه که از آخرین ایتمی که نمایش داده شده دقیقا از همونجا 10 تای بعدیش رو میگیره و کاری نداره که توی این فاصله چند تا اضافه یا کم شده ، من هم همونکار رو بکنم
نمیشه توی لاراول مثلا بگیم از ایدی فلان 10 تا بعدی رو بگیر و بیار
اگر اینطوری بشه همه چیز حل میشه
اینطوری من نگاه میکنم ببینم آخرین ایتمی که گرفته شده توی اندروید فلان هست همون رو میفرستم میگم از اینجا 10 تا بگیر و برگردون
جهت مشکل اضافه یا کم شده های توی این فاصله هم برای صفحه یه دونه swipeRefreshLayout میگذارم که اگر خواست کلا دوباره بروزرسانی انجام بده

آقا التماس دعا لطفا اساتید بفرمایند دقیقا داره چه اتفاقی میفته من قاتی کردم
ممنون و سپاسگزارم


محمدحسن یگانه
تخصص : Full-Stack Web Developer Freel...
@mhyeganeh 2 سال پیش آپدیت شد
0

سلام.
مسئله ای که باهاش مواجه شدید خیلی رایج هست و لاراول هم یک راه حل خیلی ساده و کلید طلایی براش داره بنام :
Cursor Pagination

$users = DB::table('users')->orderBy('id')->cursorPaginate(15);

حتما یک سری به اینجا بزنید و توضیحات کاملش رو مطالعه کنید. اما به طور خلاصه تفاوت cursor pagination با pagination های معمولی رو در کوئری هایی که می‌سازند می‌تونید ببینید:

# Offset Pagination...
select * from users order by id asc limit 15 offset 15;

# Cursor Pagination...
select * from users where id > 15 order by id asc limit 15;

کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش آپدیت شد
0

سلام و روز بخیر
بسیار ممنون و سپاسگزارم از @mhyeganeh عزیز
کم کم داشتم ناامید میشدم کسی جوابم رو بده
خیلی لطف کردید استاد

من قبل از اینکه شما پاسخ بدید با سرچ هایی که داشتم و بدون اطلاع از این چیزی که فرمودید به این راه حل رسیدم که بیام آخرین آیدی موجود در جیسانی که دریافت کردم رو بگیرم و توی درخواست بعدی بگم آیدی حتما کوچکتر از ایدی آخری که گرفتم باشه و اینطوری مشکل حل شد :
یعنی این شکلی شد :

        if ($request->last_id != null){
            $event = ProfileEvent::where('profile_id', $id)
                ->where('id','<',$request->last_id)
                ->orderBy('id', 'DESC')
                ->paginate(10);
        } else {
            $event = ProfileEvent::where('profile_id', $id)
                ->orderBy('id', 'DESC')
                ->paginate(10);
        }
$last_id = $event->last()['id'];

البته به جای paginate فکر کنم از take هم استفاده میکردم فرقی نمی کرد در هر صورت تا حدودی انجام شده بود ولی این چیزی که شما فرمودید خیلی عالی و کاربردی بود توی این حالت یک nextPageUrl() وجود داره که هر بار پس از کش داده ها میگیرمش و برای درخواست بعدی اون رو میفرستم و داده های بعدی رو میگیرم تا زمانیکه null نشده این کار ادامه پیدا میکنه و خیلی هم تمیز کار در میاد
آقا دم شما و دم لاراول گرم
خیلی لطف کردید ...


محمدحسن یگانه
تخصص : Full-Stack Web Developer Freel...
@mhyeganeh 2 سال پیش مطرح شد
0

موفق و پیروز باشید. 🌹


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام