ورود

View Full Version : بهریت روش برای ارسال متد پست (همراه با پارامتر) و گرفتن رشته به صورت متوالی چیست؟



kolibri
دوشنبه 27 فروردین 1397, 12:20 عصر
سلام؛
من یک سایت شخص ثالث دارم که می خوام از اون برای گرفتن اطلاعات لازم استفاده کنم.
اطلاعات دریافتی جیسان نیست و کدهای HTML هست (رشته)
کاربر، چند شناسه در برنامه ثبت کرده و برنامه باید در زمان‌های مشخصی، اونها رو چک کنه و نتیجه رو اعلام کنه.
من از کتابخانه Volley استفاده کردم، اما وقتی شناسه ها رو از دیتابیس دریافت و به وسیله یک حلقه به Volley می‌فرستم، برنامه کرش می کند، چون هنوز پاسخ قبلی دریافت نشده و...

راه حل چیست؟



public void Refresh(Context context, Integer X ,Cursor C) throws InterruptedException {
final DBConteroler dbConteroler = new DBConteroler(context);
SQLiteDatabase sqLiteDatabase = dbConteroler.getReadableDatabase();
Cursor cursor = C;

cursor.move(X);
if (cursor.getCount() > 0) {
ID = cursor.getString(1);


RequestQueue queue = Volley.newRequestQueue(context);
final String finalID = ID;
StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://url", new Response.Listener<String>() {


@Override
public void onResponse(String response) {



}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}


}) {
@Override
protected Map<String, String> getParams() {

Map<String, String> params = new HashMap<String, String>();
params.put("scripmanager1", "pnlMain|btnSearch");
params.put("__LASTFOCUS", "");
params.put("__EVENTTARGET", "btnSearch");
params.put("__ASYNCPOST", "true");


return params;
}



@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
params.put("Connection", "keep-alive");
params.put("X-Requested-With", "XMLHttpRequest");
params.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
return params;
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));


queue.add(stringRequest);
}


}

farhad_shiri_ex
دوشنبه 27 فروردین 1397, 13:54 عصر
اما وقتی شناسه ها رو از دیتابیس دریافت و به وسیله یک حلقه به Volley می‌فرستم

منظورتون از ارسال به volly خیلی مبهم هست !
بعد از طرفی توی متد onResponse که چیزی دریافت نمیکنید یا شاید هم خودتون به خاطر مشاهده نشدن سورس تون ننوشتین.
به هر حال اگر منظورتون اینه که این متد تو حلقه چک میکنید که خوب این دو خط اول متد

final DBConteroler dbConteroler = new DBConteroler(context);
SQLiteDatabase sqLiteDatabase = dbConteroler.getReadableDatabase();

اصلا کار بهینه ای نیست.!
بهتر بود شما شرح پیغام خطای برنامه رو اینجا بذارید فکر کنم بهتر باشه

kolibri
دوشنبه 27 فروردین 1397, 15:18 عصر
منظورتون از ارسال به volly خیلی مبهم هست !


منظورم این هست که اطلاعات لازم رو به این متد میفرستم.



بعد از طرفی توی متد onResponse که چیزی دریافت نمیکنید یا شاید هم خودتون به خاطر مشاهده نشدن سورس تون ننوشتین.


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



به هر حال اگر منظورتون اینه که این متد تو حلقه چک میکنید که خوب این دو خط اول متد

final DBConteroler dbConteroler = new DBConteroler(context);
SQLiteDatabase sqLiteDatabase = dbConteroler.getReadableDatabase();

اصلا کار بهینه ای نیست.!


منظورم همینه، من مثلا 100 رکورد دارم تو دیتابیس، باید برای 100 تاش متد پست بفرستم. ولی اولی هنوز پردازش نشده، دومی هم ارسال میشه.

و البته خوشحال میشم روش بهینه رو هم بهم بگید تا یاد بگیرم. چون من به صورت تجربی یاد گرفتم و خیلی مشکل دارم.



بهتر بود شما شرح پیغام خطای برنامه رو اینجا بذارید فکر کنم بهتر باشه


این هم خطا:


E/AndroidRuntime: FATAL EXCEPTION: main
Process: ir.radin.posta.posta, PID: 31419
android.database.CursorIndexOutOfBoundsException: Index 4 requested, with a size of 4
at android.database.AbstractCursor.checkPosition(Abst ractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosit ion(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString( AbstractWindowedCursor.java:50)
at ir.radin.posta.posta.App.DBConteroler.Refresh(DBCo nteroler.java:172)
at ir.radin.posta.posta.MainActivity$1.onRefresh(Main Activity.java:100)
at android.support.v4.widget.SwipeRefreshLayout$1.onA nimationEnd(SwipeRefreshLayout.java:188)
at android.support.v4.widget.CircleImageView.onAnimat ionEnd(CircleImageView.java:106)
at android.view.ViewGroup.finishAnimatingView(ViewGro up.java:6734)
at android.view.View.draw(View.java:19029)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.draw(View.java:19126)
at android.view.View.updateDisplayListIfDirty(View.ja va:18073)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.draw(View.java:19126)
at android.view.View.updateDisplayListIfDirty(View.ja va:18073)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.updateDisplayListIfDirty(View.ja va:18064)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.updateDisplayListIfDirty(View.ja va:18064)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.updateDisplayListIfDirty(View.ja va:18064)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.updateDisplayListIfDirty(View.ja va:18064)
at android.view.View.draw(View.java:18851)
at android.view.ViewGroup.drawChild(ViewGroup.java:42 14)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java :4000)
at android.view.View.draw(View.java:19126)
at com.android.internal.policy.DecorView.draw(DecorVi ew.java:785)
at android.view.View.updateDisplayListIfDirty(View.ja va:18073)
at android.view.ThreadedRenderer.updateViewTreeDispla yList(ThreadedRenderer.java:643)
at android.view.ThreadedRenderer.updateRootDisplayLis t(ThreadedRenderer.java:649)
at android.view.ThreadedRenderer.draw(ThreadedRendere r.java:757)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2 980)
at android.view.ViewRootImpl.performDraw(ViewRootImpl .java:2794)
at android.view.ViewRootImpl.performTraversals(ViewRo otImpl.java:2347)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl .java:1386)
at android.view.ViewRootImpl$TraversalRunnable.run(Vi ewRootImpl.java:6733)
at android.view.Choreographer$CallbackRecord.run(Chor eographer.java:911)
at android.view.Choreographer.doCallbacks(Choreograph er.java:723)
at android.view.Choreographer.doFrame(Choreographer.j ava:658)
at android.view.Choreographer$FrameDisplayEventReceiv er.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789 )
at android.os.Handler.dispatchMessage(Handler.java:98 )
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.jav a:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller .run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit .java:767)

farhad_shiri_ex
دوشنبه 27 فروردین 1397, 16:15 عصر
دوست عزیز! پیامتون رو دیدم.!
وقتی از وب سرویسهای rest که استفاده میشه شما یه درخواست با یکسری پارامتر دارید ارسال میکنید به سرور سایت تون و در جواب هم صبر میکنید تا رشته ای که میخواهید برگرده حالا شما دارید یکسری درخواست رو پشت سرهم تو یک حلقه ارسال میکنید یعنی هیچ کنترلی ندارید که کدوم مقادیر برگشته کدوم برنگشته.!
بهتره برای اینجور درخواست ها حتما از روش Parallel استفاده کنید یعنی پردازش هاتون رو به صورت موازی انجام بدید چون وقتی که شما با volly اطلاعات ارسال میکنید خود کلاس براتون یکسری صف تشکیل میده با این دستور queue.add(stringRequest); ولی مشکل اینجاست که شما این Request هارو به حال خودشون رها کردین پس شما هم باید سمت کلاس خودتون بجای استفاده از حلقه از یک کلاس موازی سازی استفاده کنید.
و هر ارسال رو به صورت موازی به صورت سنکرون انجام بدید یعنی غیر همزمان اینکار انجام بشه یعنی تا دریافت اطلاعات از سرور منتظر جواب بمونه.! البته این رو از روی کدتون میگم شاید هم بتونیم آسنکرون یعنی همزمان این ارسال و دریافت هارو پردازش کنید اون دیگه باشماست.
می تونید از فریم وورک ForkJoinTask استفاده کنید که مثال براش توی همین تالار گذاشتم ویا اینکه میتونید خودتون یه کلاس موازی Parallel با حوضچه های نخ بنویسید که البته هر دوروش سختی هایی داره ولی مطمئنا بعد ها بدردتون میخوره شاید هم بگید میتونید از کلاس AsyncTask استفاده کنید. اگرهم که میخواهید ساده تر باشه میتونید با دیدن این کد که از کلاس Count Down Latch استفاده میکنه ایده بگیرید برای غیرهمزمان کردن درخواست ها فقط بگم موازی سازی نیست میتونید خودتون توی نخ ها و حوضچه ای نخ ها مثل (ThreadPoolExecuter) از این متد استفاده کنید یعنی نوشتن داده های هر نخ براتون راحتت میکنه.

public synchronized long executeTasksDownLatch(final Runnable action, int concurrency) throws InterruptedException {
final CountDownLatch ready = new CountDownLatch(concurrency);
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch done = new CountDownLatch(concurrency);
for (int i = 0; i < concurrency; i++) {
THREAD_POOL_EXECUTOR.execute(() -> {
ready.countDown(); // decrement concurrency - 1
try {
start.await(); // wait the startMyAsyncTask latch until action latch is finished.!
action.run(); // run the task in executor thread.
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // if thread is exception interrupted.
} finally {
done.countDown(); // if action latch success the run decrement concurrency - 1
// and loop the for and startMyAsyncTask the next action task.
}
});
}
ready.await(); // wait until all threads task is finished.
long startNanos = System.nanoTime();
Log.i("startNanos", "executeTasksDownLatch startMyAsyncTask: "+startNanos);
start.countDown();// decrement count - 1 = 0
done.await(); // wait until all task is finally run is ok.
Log.i("startNanos", "executeTasksDownLatch end: "+System.nanoTime());
return TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startNanos); // calculate the elapsed time for all threads is finished.
}

برای کد بالا هم به اختصار اگر بخواهم بگم گاهی می خواهید که یک نخ تا زمان رخ دادن یک رویداد منتظر بمونه ، یک CounDownLatch با یک شمارش از تعداد رویدادها که در سازنده کلاس تعریف میکنیم ساخته میشه که هر بار latch چک میشه تا زمانی که شمارش صفر بشه تا latch باز بشه بنابراین تو این متد تعداد رویداد هارو مشخص میکنید بعد یک عملیات اتفاق می افتد برای اون پردازش تا وقتی که همه عملیاتها تمام بشن وکنترل از متد خارج بشه البته این یک ایده است که عرض کردم کلا تکنیکهای زیادی داره هم زمانی و موازی سازی توی جاوا
درمنطق برنامه شما موازی سازی داریم که یکسری پردازش موازی هم باید کار کنند که شاید نسبت برگشتن پاسخ هاشون متغیر باشه پس هر Request موازی در یک نخ دیگه ای کنترل میشه و البته در جدول شما نوشته میشه و اینم بگم که فقط حواستون به نحوه نوشتن این داده ها توی جدولتون باشه اگر تقدم و تاخر ویا بهتر بگم یکپارچه سازی توی جداول تون لحاظ شده حتما بهش توجه کنید.
قطعا موازی سازی نیاز دارید ولی چون من شرایط یکپارچگی دیتابیس سرورتون و همچنین بانکهای لوکال تون رو نمیدونم نمیتونم بگم که این موازی سازی باید هم زمان باشه یا غیر همزمان به شرایط شما بستگی داره.
یه مثال کوچیک برای موازی سازی هم فکر کنید دوتا گیشه بلیط فروشی دارید وباالطبع دوصف 200 نفری هم برای تهیه بلیط حالا اگر تعداد گیشه ها رو بیشتر کنید هم صف هاتون سبک تر میشن و هم همزمان تعداد زیادی بلیط می فروشید در اینجا باجه های بلیط فروشی همون موازی کردن درخواستهاست.
اگرهم که به سورسی نیاز دارید که خوب با دیدن این متد نمیشه یک کد موازی نوشت ولی شما خودتون شروع کنید اگر کمکی بود من و خیلی از دوستان دیگه هم هستند کمک میکنن

kolibri
دوشنبه 27 فروردین 1397, 17:26 عصر
دوست عزیز! پیامتون رو دیدم.!
وقتی از وب سرویسهای rest که استفاده میشه شما یه درخواست با یکسری پارامتر دارید ارسال میکنید به سرور سایت تون و در جواب هم صبر میکنید تا رشته ای که میخواهید برگرده حالا شما دارید یکسری درخواست رو پشت سرهم تو یک حلقه ارسال میکنید یعنی هیچ کنترلی ندارید که کدوم مقادیر برگشته کدوم برنگشته.!
بهتره برای اینجور درخواست ها حتما از روش Parallel استفاده کنید یعنی پردازش هاتون رو به صورت موازی انجام بدید چون وقتی که شما با volly اطلاعات ارسال میکنید خود کلاس براتون یکسری صف تشکیل میده با این دستور queue.add(stringRequest); ولی مشکل اینجاست که شما این Request هارو به حال خودشون رها کردین پس شما هم باید سمت کلاس خودتون بجای استفاده از حلقه از یک کلاس موازی سازی استفاده کنید.
و هر ارسال رو به صورت موازی به صورت سنکرون انجام بدید یعنی غیر همزمان اینکار انجام بشه یعنی تا دریافت اطلاعات از سرور منتظر جواب بمونه.! البته این رو از روی کدتون میگم شاید هم بتونیم آسنکرون یعنی همزمان این ارسال و دریافت هارو پردازش کنید اون دیگه باشماست.
می تونید از فریم وورک ForkJoinTask استفاده کنید که مثال براش توی همین تالار گذاشتم ویا اینکه میتونید خودتون یه کلاس موازی Parallel با حوضچه های نخ بنویسید که البته هر دوروش سختی هایی داره ولی مطمئنا بعد ها بدردتون میخوره شاید هم بگید میتونید از کلاس AsyncTask استفاده کنید. اگرهم که میخواهید ساده تر باشه میتونید با دیدن این کد که از کلاس Count Down Latch استفاده میکنه ایده بگیرید برای غیرهمزمان کردن درخواست ها فقط بگم موازی سازی نیست میتونید خودتون توی نخ ها و حوضچه ای نخ ها مثل (ThreadPoolExecuter) از این متد استفاده کنید یعنی نوشتن داده های هر نخ براتون راحتت میکنه.

public synchronized long executeTasksDownLatch(final Runnable action, int concurrency) throws InterruptedException {
final CountDownLatch ready = new CountDownLatch(concurrency);
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch done = new CountDownLatch(concurrency);
for (int i = 0; i < concurrency; i++) {
THREAD_POOL_EXECUTOR.execute(() -> {
ready.countDown(); // decrement concurrency - 1
try {
start.await(); // wait the startMyAsyncTask latch until action latch is finished.!
action.run(); // run the task in executor thread.
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // if thread is exception interrupted.
} finally {
done.countDown(); // if action latch success the run decrement concurrency - 1
// and loop the for and startMyAsyncTask the next action task.
}
});
}
ready.await(); // wait until all threads task is finished.
long startNanos = System.nanoTime();
Log.i("startNanos", "executeTasksDownLatch startMyAsyncTask: "+startNanos);
start.countDown();// decrement count - 1 = 0
done.await(); // wait until all task is finally run is ok.
Log.i("startNanos", "executeTasksDownLatch end: "+System.nanoTime());
return TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startNanos); // calculate the elapsed time for all threads is finished.
}

برای کد بالا هم به اختصار اگر بخواهم بگم گاهی می خواهید که یک نخ تا زمان رخ دادن یک رویداد منتظر بمونه ، یک CounDownLatch با یک شمارش از تعداد رویدادها که در سازنده کلاس تعریف میکنیم ساخته میشه که هر بار latch چک میشه تا زمانی که شمارش صفر بشه تا latch باز بشه بنابراین تو این متد تعداد رویداد هارو مشخص میکنید بعد یک عملیات اتفاق می افتد برای اون پردازش تا وقتی که همه عملیاتها تمام بشن وکنترل از متد خارج بشه البته این یک ایده است که عرض کردم کلا تکنیکهای زیادی داره هم زمانی و موازی سازی توی جاوا
درمنطق برنامه شما موازی سازی داریم که یکسری پردازش موازی هم باید کار کنند که شاید نسبت برگشتن پاسخ هاشون متغیر باشه پس هر Request موازی در یک نخ دیگه ای کنترل میشه و البته در جدول شما نوشته میشه و اینم بگم که فقط حواستون به نحوه نوشتن این داده ها توی جدولتون باشه اگر تقدم و تاخر ویا بهتر بگم یکپارچه سازی توی جداول تون لحاظ شده حتما بهش توجه کنید.
قطعا موازی سازی نیاز دارید ولی چون من شرایط یکپارچگی دیتابیس سرورتون و همچنین بانکهای لوکال تون رو نمیدونم نمیتونم بگم که این موازی سازی باید هم زمان باشه یا غیر همزمان به شرایط شما بستگی داره.
یه مثال کوچیک برای موازی سازی هم فکر کنید دوتا گیشه بلیط فروشی دارید وباالطبع دوصف 200 نفری هم برای تهیه بلیط حالا اگر تعداد گیشه ها رو بیشتر کنید هم صف هاتون سبک تر میشن و هم همزمان تعداد زیادی بلیط می فروشید در اینجا باجه های بلیط فروشی همون موازی کردن درخواستهاست.
اگرهم که به سورسی نیاز دارید که خوب با دیدن این متد نمیشه یک کد موازی نوشت ولی شما خودتون شروع کنید اگر کمکی بود من و خیلی از دوستان دیگه هم هستند کمک میکنن

ممنون از پاسخ گویی
چیزهایی که فرمودید خیلی بیشتر از سطح دانش من نسبت به برنامه نویسی است.
دیتابیس من دارای یک جدول است. از دیتابیس کدهای رهگیری رو می گیرم و به این متد میفرستم تا در پارامتر مربوطه (در کدی که براتون فرستادم با عنوان finalID می تونید پیداش کنید) پست میشه.
حالا من می خوام هر بار یک کد رهگیری فرستاده بشه، اگر وضعیت بسته تغییری کرده باشه، کاری رو انجام بده، اگرم نه هم که هیچ.

farhad_shiri_ex
دوشنبه 27 فروردین 1397, 18:20 عصر
ممنون از پاسخ گویی
چیزهایی که فرمودید خیلی بیشتر از سطح دانش من نسبت به برنامه نویسی است.
دیتابیس من دارای یک جدول است. از دیتابیس کدهای رهگیری رو می گیرم و به این متد میفرستم تا در پارامتر مربوطه (در کدی که براتون فرستادم با عنوان finalID می تونید پیداش کنید) پست میشه.
حالا من می خوام هر بار یک کد رهگیری فرستاده بشه، اگر وضعیت بسته تغییری کرده باشه، کاری رو انجام بده، اگرم نه هم که هیچ.

چشم دوست عزیز سعی میکنم به صورت الگوریتم پارالل یه برنامه همینجا بذارم با همین متدی که برام فرستادی.!

kolibri
چهارشنبه 29 فروردین 1397, 14:29 عصر
کسی پاسخی نداره؟
یا یک آموزش خوب در این باره؟

kolibri
سه شنبه 04 اردیبهشت 1397, 08:13 صبح
همچنان در انتظار یک پاسخ...