วิธีเข้าถึงกล่องโต้ตอบจากกระบวนการเบื้องหลัง

ฉันมี ListView พร้อมอะแดปเตอร์แบบกำหนดเอง และมันแสดงรายการ wifi รอบตัวฉัน เมื่อคลิกรายการใดรายการหนึ่ง ฉันจะแสดงกล่องโต้ตอบพร้อมรายละเอียด กล่องโต้ตอบเป็นคลาสที่กำหนดเองที่ได้มาจาก DialogFragment และแสดงโดยใช้รหัสนี้หลังจากการสแกน Wifi เสร็จสิ้น:

private class WifiScanReceiver extends BroadcastReceiver {
        public void onReceive(Context c, Intent intent) {
            List<ScanResult> wifiScanList = wifi.getScanResults();
            Log.i("WifiAnal", "rec");

            lv.setAdapter(new WifiListAdapter(getApplicationContext(), R.layout.itemlistrow, wifiScanList));
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    ScanResult listItem = (ScanResult)lv.getItemAtPosition(position);
                    WifiDetailsDialogFragment d = new WifiDetailsDialogFragment();

                    // Supply num input as an argument.
                    Bundle args = new Bundle();
                    args.putString("ssid", listItem.SSID);

                    d.setArguments(args);

                    d.show(getSupportFragmentManager(), "fir");

                    // TODO: PUT ASYNC CALL HERE AND PROCESS FETCHED DATA.
                    // TODO: SHOW ASYNC RESULT ON OPEN DIALOG

                }

            });

            mSwipeRefreshLayout.setRefreshing(false);
        }
    }

คลาส WifiDetailsDialogFragment ของฉันดูแลการขยายเค้าโครง xml และแสดงอย่างถูกต้องที่ด้านบนของแอปด้วยปุ่มตกลง

ทีนี้ลองนึกภาพว่าฉันแสดงกล่องโต้ตอบและตอนนี้ฉันต้องการรันงานพื้นหลัง (เช่นดึงรายละเอียดเพิ่มเติมจากฐานข้อมูลบนเซิร์ฟเวอร์ภายนอก) และหลังจากที่ฉันทำเสร็จแล้ว หากกล่องโต้ตอบยังคงเปิดอยู่ ให้วางผลลัพธ์ลงในโครงร่าง (น่าจะจัดการค่าของบางรายการ) TextViews ที่มีอยู่แล้วและสูงเกินจริง) ถ้าปิดแล้วไม่ต้องทำอะไรเลย

ฉันจะเข้าถึงวิดเจ็ตเลย์เอาต์ของฉันจากกระบวนการที่ทำงานในพื้นหลังที่เริ่มต้นโดย onItemClick ได้อย่างไร ฉันพยายาม d.getView() แต่สิ่งนี้ส่งคืน null วิธีที่ถูกต้องคือผ่าน FragmentManager หรือไม่ ฉันไม่ต้องการวาดบทสนทนาใหม่ แต่ต้องการแก้ไขสมาชิกที่มีอยู่

ขอบคุณ!


comment
คุณไม่สามารถเข้าถึงมุมมองเธรด UI จากเธรดพื้นหลังของคุณ เมื่อคุณมีค่าที่ดึงมาจาก DB หรือจากการเรียกเซิร์ฟเวอร์บนวิธี runOnUIThread ให้ทำสิ่งที่คุณต้องการจะทำกับกล่องโต้ตอบของคุณ   -  person dex    schedule 21.10.2015
comment
ฉันจะรับการอ้างอิงถึง TextView ภายในกล่องโต้ตอบจากภายใน runOnUIThread ได้อย่างไร เค้าโครงขยายจากภายใน onItemClick   -  person michnovka    schedule 21.10.2015
comment
คุณต้องส่งผ่านนั้นที่สูงเกินจริงไปยังเธรดพื้นหลังผ่านการอ้างอิงที่อ่อนแอฉันเดา   -  person dex    schedule 21.10.2015


คำตอบ (2)


ถ้าคุณเพียงต้องการเข้าถึงส่วนของคุณคุณก็สามารถใช้ได้

getSupportFragmentManager().findFragmentByTag("fir")

แท็กนี้จะต้องได้รับการกำหนดในขณะที่ทำธุรกรรมส่วนของคุณ (ในกรณีของคุณ show() เนื่องจากเป็น DialogFragment

แต่ฉันควรแนะนำว่าโค้ดที่คุณกำหนดไว้ด้านบนดูแปลกนิดหน่อย คุณคาดหวังว่าจะได้ผลลัพธ์จากการโทรแบบ async ของคุณที่นั่นอย่างไร หากคุณยังคงใช้โค้ดเช่นนี้ต่อไป คุณจะได้รับ android.os.NetworkOnMainThreadException

เพื่อหลีกเลี่ยงไม่ให้คุณควรสร้าง AsyncTask และจัดการ UI ของคุณโดยใช้เมธอด onPostExecute ซึ่งคุณจะกลับสู่ลูปหลัก

person luis.mazoni    schedule 21.10.2015
comment
ฉันโทรโดยใช้ AsyncTask นี่คือที่ที่ฉันเรียกใช้งาน โดยจะมีวิธีการของตัวเอง รวมถึงวิธี onPostExecute และนั่นคือที่ที่ฉันจะต้องจัดการกับ TextView โซลูชันนี้จะใช้งานได้ภายใต้สถานการณ์เหล่านี้หรือไม่ - person michnovka; 21.10.2015
comment
getFragment ต้องใช้ Bundle เป็นพารามิเตอร์แรกด้วย ฉันควรใส่อะไรที่นั่น? เหตุใดจึงต้องการมัน มันสร้างมันขึ้นมาตั้งแต่ต้นหรือไม่? - person michnovka; 21.10.2015
comment
ขออภัย ใช้: findFragmentByTag - person luis.mazoni; 21.10.2015
comment
ฉันเพิ่มโค้ดนี้ ((WifiDetailsDialogFragment)getSupportFragmentManager().findFragmentByTag("fir")).updateUI(); หลัง d.show(getSupportFragmentManager(), "fir"); และฉันได้รับ nullPointerException ซึ่งหมายความว่าฉันไม่ได้รับส่วนที่ถูกต้องด้วยวิธีนี้ ฉันได้รับ null แทน... มีความคิดบ้างไหมว่าทำไม ป.ล. updateUI() เป็น func ที่กำหนดไว้ในส่วนที่กำหนดเองของฉันซึ่งจะดูแลการเปลี่ยนแปลงที่จำเป็น - person michnovka; 21.10.2015

ฉันขอแนะนำให้คุณใช้ Otto เพื่อส่งกิจกรรมจากเธรดพื้นหลังของคุณไปยังตรรกะ UI กิจกรรมเหล่านี้อาจมีข้อมูลอะไรก็ได้ที่คุณต้องการ ขั้นตอนที่คุณจะต้องปฏิบัติตามคือ:

  • แทรกบัสของคุณทั้งในเธรดพื้นหลังและส่วนของกล่องโต้ตอบ (อาจแตกต่างกันไปตามโซลูชันตัวจัดการการพึ่งพาของคุณ)
  • register() ชิ้นส่วนของคุณไปที่รถบัส
  • สร้างวิธีการรับเหตุการณ์และใส่คำอธิบายประกอบด้วย @Subscribe
  • post() เหตุการณ์จากเธรดพื้นหลัง (ในการทำเช่นนั้นคุณจะต้องไปที่ looper หลัก แต่สามารถทำได้ง่าย ๆ โดยการแก้ไข otto bus เช่นเดียวกับโค้ดด้านล่าง)

    public class MainThreadBus extends Bus {
     private final Handler handler = new Handler(Looper.getMainLooper());
    
     @Override public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            super.post(event);
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    MainThreadBus.super.post(event);
                }
            });
        }
    }
    

แนะนำรหัสนี้ในคำตอบนี้: จะส่งเหตุการณ์จากบริการไปยังกิจกรรมด้วย Otto event bus ได้อย่างไร

การเขียนโซลูชันของคุณด้วยวิธีนี้คุณจะปลอดภัยยิ่งขึ้นเนื่องจากคุณสามารถ unregister() ส่วนของคุณในเมธอด onPause ได้ ดังนั้นคุณจึงไม่จำเป็นต้องตรวจสอบว่าส่วนย่อยยังคงแนบอยู่กับกิจกรรมหรือไม่เมื่อจัดการกับ UI ของมัน

person luis.mazoni    schedule 21.10.2015
comment
ขอบคุณ แต่ดูเหมือนจะแพงไปหน่อยสำหรับสิ่งง่ายๆเช่นนี้ ฉันกำลังมองหาอุปกรณ์ที่ไม่มีส่วนประกอบของบุคคลที่สาม - person michnovka; 21.10.2015