getExtractedText เกี่ยวกับคำเตือน InputConnection ที่ไม่ใช้งานบน Android


129

ฉันได้รับคำเตือนต่อไปนี้ใน logcat ของฉัน

getExtractedText on inactive InputConnection

ฉันไม่สามารถหาเหตุผลที่อยู่เบื้องหลังมันได้ กรุณาช่วย


4
ฉันไม่เข้าใจว่าคำถามนี้มีอะไรคลุมเครือ / คลุมเครือ / ไม่สมบูรณ์? ฉันได้รับคำเตือนนี้ใน logcat ขณะใช้งานแอปฉันต้องการทราบเหตุผลของคำเตือนนี้
pankajagarwal

2
ฉันยังเห็นสิ่งนี้ในแอปพลิเคชันของฉันที่ฉันกำลังพัฒนาและฉันไม่รู้ว่ามันมาจากไหนหรือทำไม ถ้าใครเคยเจอกรุณาโพสต์ความคิดเห็น จริงๆแล้วมันแสดงคำเตือนที่แตกต่างกันมากมายจากนั้น "getExtractedText" ฉันยังเห็น: "beginBatchEdit", "endBatchEdit", "getTextBeforeCursor" และอื่น ๆ อีกมากมาย
ช่วง

1
เป็นผู้ดูแลที่ดูคำถามนี้ ถ้าไม่เช่นนั้นก็ควรเพราะถ้าพวกเขายังคงเชื่อว่าคำถามนี้คลุมเครือและไม่ชัดเจนแม้ว่าจะมีการโหวตเพิ่มขึ้น 14 ครั้งฉันก็ไม่รู้จะพูดอะไร
pankajagarwal

ฉันเห็นด้วยนี่เป็นปัญหาที่ฉันต้องแก้ไขด้วย ฉันไม่รู้สาเหตุ
JonWillis

3
คุณมีรหัสอะไรที่ทำให้เกิดข้อผิดพลาดนี้
Bill the Lizard

คำตอบ:


44

ฉันพบปัญหาที่คล้ายกัน logcat ของฉัน:

W/IInputConnectionWrapper(21214): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(21214): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper(21214): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper(21214): getTextAfterCursor on inactive InputConnection
...
I/Choreographer(20010): Skipped 30 frames!  The application may be doing too much work on its main thread.

สถานการณ์ของฉัน: ฉันมี EditText ดูประเภทผู้ใช้เป็น EditText จะถูกล้างเมื่อผู้ใช้กดปุ่ม รายการ InputConnection ที่ไม่ได้ใช้งานจำนวนมากจะสตรีมออกมาเมื่อฉันกดปุ่มอย่างรวดเร็ว

Ex:

editText.setText(null);

บรรทัดสุดท้ายใน logcat ของฉันด้านบนเป็นตัวบ่งชี้ที่ดีว่ากำลังเกิดอะไรขึ้น แน่นอนว่า InputConnection นั้นเต็มไปด้วยคำขอให้ล้างข้อความ ฉันได้ลองแก้ไขรหัสเพื่อตรวจสอบความยาวของข้อความก่อนที่จะพยายามล้าง:

if (editText.length() > 0) {
    editText.setText(null);
}

สิ่งนี้ช่วยบรรเทาปัญหาในการกดปุ่มอย่างรวดเร็วไม่ทำให้สตรีมคำเตือนของ IInputConnectionWrapper อีกต่อไป อย่างไรก็ตามสิ่งนี้ยังคงมีปัญหาเมื่อผู้ใช้สลับไปมาอย่างรวดเร็วระหว่างการพิมพ์บางสิ่งบางอย่างและการกดปุ่มหรือกดปุ่มเมื่อแอปมีโหลดเพียงพอเป็นต้น

โชคดีที่ผมพบวิธีอื่นเพื่อข้อความที่ชัดเจน: Editable.clear () ด้วยสิ่งนี้ฉันไม่ได้รับคำเตือนเลย:

if (editText.length() > 0) {
    editText.getText().clear();
}

โปรดทราบว่าคุณควรจะต้องการที่จะล้างรัฐเข้าทั้งหมดและไม่เพียงข้อความ (ข้อความอัตโนมัติ autocap, มัลติแทยกเลิก), คุณสามารถใช้TextKeyListener.clear (แก้ไขจ)

if (editText.length() > 0) {
    TextKeyListener.clear(editText.getText());
}

1
ฉันได้รับคำเตือน IInputConnectionWrapper ด้วยและแอพของฉันก็เกือบจะ ANR แล้ววิธีการ clear () ใช้ได้ผลสำหรับฉัน ...
กล่อง

17

ปรับปรุง:

เหตุผลที่ฉันได้รับคำเตือน InputConnection ไม่ใช่เพราะฉันตั้งค่าข้อความไว้ที่ไหน (เช่นในการonTextChangedโทรกลับหรือafterTextChanged) - เป็นเพราะฉันใช้setTextมันเป็นเพราะผมใช้

ฉันแก้ไขปัญหาได้โดยโทร:

hiddenKeyboardText.getText().clear();
hiddenKeyboardText.append("some string");

หมายเหตุ: ฉันยังคงโทรออกในการafterTextChangedโทรกลับแม้ว่าจะใช้งานได้โดยไม่มีคำเตือนจากontextChangedเช่นกัน

คำตอบก่อนหน้า:

ฉันได้รับข้อความที่เหมือนกันใน Logcat เช่นกันแม้ว่าสถานการณ์ของฉันจะแตกต่างกันเล็กน้อย ฉันต้องการอ่านอักขระทุกตัวที่เข้ามาใน EditText (หรือประกอบด้วยอักขระ / ข้อความที่วาง) จากนั้นรีเซ็ต EditText ที่เป็นปัญหาเป็นสตริงเริ่มต้นเริ่มต้น

ส่วนข้อความที่ชัดเจนจะทำงานตามโซลูชันของ Johnson ด้านบน อย่างไรก็ตามการรีเซ็ตข้อความเป็นปัญหาและฉันได้รับคำเตือนการเชื่อมต่ออินพุต

ในขั้นต้นของฉันonTextChanged(CharSequence s, ...)ถูกกำหนดไว้ดังนี้:

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (isResettingKeyboard)
        return;

    // ... do what needs to be done

    resetKeyboardString();

}

public void resetKeyboardString()
{
    isResettingKeyboard = true;

    hiddenKeyboardText.getText().clear();
    hiddenKeyboardText.setText(keyboardInitString);
    hiddenKeyboardText.setSelection(defaultKeyboardCursorLocation);

    isResettingKeyboard = false;
}

เมื่อonTextChanged(...)ถูกเรียก EditText จะอยู่ในโหมดอ่านอย่างเดียว ฉันไม่แน่ใจว่านี่หมายความว่าเราไม่สามารถทำอะไรได้มากกว่าการโทรgetText.clear()(การsetText(...)โทรสร้างคำเตือน inputConnection ด้วย)

อย่างไรก็ตามการโทรกลับafterTextChanged(Editable s)เป็นสถานที่ที่เหมาะสมในการตั้งค่าข้อความ

@Override
public void afterTextChanged(Editable s) {

    if (isResettingKeyboard)
        return;

    resetKeyboardString();

    // ... 
}

ป่านนี้ทำงานโดยไม่มีคำเตือนใด ๆ


ฉันก็มีปัญหาเหมือนกัน สิ่งที่ฉันรู้ก็คือแม้ว่าโซลูชันของคุณจะทำให้คำเตือน InputConnection หายไป แต่ฉันสังเกตเห็นว่า afterTextChangedมีการเรียกใช้วิธีการhiddenKeyboardText.getText().clear();ดังhiddenKeyboardText.append("some string");กล่าวและควรคำนึงถึงข้อเท็จจริงนี้ด้วย +1 จากฉัน!
นิค

@Nick true - สำคัญเพื่อให้แน่ใจว่าif (isResettingKeyboard) return;อยู่ด้านบน ...
ahash

7

จากเอกสารความช่วยเหลือ

http://developer.android.com/reference/android/view/inputmethod/InputConnection.html

อินเทอร์เฟซ InputConnection เป็นช่องทางการสื่อสารจาก InputMethod กลับไปยังแอ็พพลิเคชันที่รับอินพุต ใช้เพื่อดำเนินการต่างๆเช่นอ่านข้อความรอบ ๆ เคอร์เซอร์ส่งข้อความไปยังกล่องข้อความและส่งเหตุการณ์สำคัญไปยังแอปพลิเคชัน

นอกจากนี้การอ่านเพิ่มเติมแสดงให้เห็น

getExtractedText (): วิธีการนี้อาจล้มเหลวทั้งหากการเชื่อมต่อการป้อนข้อมูลได้กลายเป็นที่ไม่ถูกต้อง (เช่น crashing กระบวนการของมัน) หรือลูกค้าจะใช้เวลานานเกินไปที่จะตอบสนองกับข้อความ (มันจะได้รับคู่วินาทีเพื่อกลับ) ไม่ว่าในกรณีใดค่าว่างจะถูกส่งกลับ

ดูเหมือนว่าจะตรวจสอบการเปลี่ยนแปลงของข้อความดังกล่าวและแจ้งเตือนการเปลี่ยนแปลง

ในการค้นหาปัญหานี้คุณจะต้องสำรวจการสืบค้นฐานข้อมูลใด ๆ ที่คุณกำลังทำอยู่อาจจะเกี่ยวกับ listViews หรือรายการในเค้าโครง

หากคุณไม่มีมุมมองใด ๆ ตัวอย่างเช่นมันเกิดขึ้นแบบสุ่มในพื้นหลังฉันขอแนะนำว่ามันไม่ใช่ปัญหาองค์ประกอบ UI ดังนั้นให้ละเว้นฟิลด์ข้อความและอื่น ๆ อาจเป็นบริการพื้นหลังที่จัดเก็บข้อมูลในเคอร์เซอร์หรือขอเคอร์เซอร์

นอกจากนี้ปัญหาเกิดจากแอปของคุณหรือไม่ หรืออาจเป็นของคนอื่นที่คุณติดตั้งเมื่อเร็ว ๆ นี้ แสดงรายการการติดตาม logCat แบบเต็ม อาจมีคนรับรู้ปัญหานี้

ฉันจะเดาว่าถ้าคุณไม่ได้เขียนบางอย่างที่เฉพาะเจาะจงเกี่ยวกับเรื่องนี้ว่ามีใครบางคนบันทึกข้อความหรืออาจเป็นของห้องสมุดที่คุณใช้?


1
ขอบคุณฉันทำแบบสอบถาม db แต่แปลกคำเตือนนี้ไม่ปรากฏขึ้นเมื่อเรียกใช้แอปบนโปรแกรมจำลองดังนั้นอาจเป็นเพราะแอปอื่น ๆ ที่ติดตั้งในอุปกรณ์ของฉัน จะมองไปในทิศทางนี้
pankajagarwal

ฉันคิดว่า logCat ล่าสุดแสดงให้คุณเห็นว่าข้อความของคุณแตกต่างจากแอปอื่น ๆ ที่กรองแล้ว ยังไม่ได้ใช้มันเพียงพอที่จะยืนยันว่าแม้ว่า คุณสามารถสร้างแอปเปล่าใหม่และดูแมวบันทึกเพื่อดูว่ามีข้อผิดพลาดเกิดขึ้นหรือไม่ซึ่งจะเป็นการกำจัดแอปของคุณ จากการเป็นปัญหา
Emile

@frieza ไม่จำเป็นต้องเป็นแอพอื่น ฉันได้เพิ่ม ArrayAdapter ด้วย sqlite และตอนนี้ฉันก็ได้รับคำเตือนนี้ทางโทรศัพท์เช่นกัน ฉันเดาว่าคุณไม่เห็นข้อผิดพลาดในอีมูเลเตอร์เป็นเพราะมันทำงานช้าและเกณฑ์ประสิทธิภาพจึงถูกปิดใช้งานตามมา
alandarev

7

ฉันประสบปัญหาเดียวกัน คำเตือนปรากฏขึ้นเมื่อเปิดใช้งานซอฟต์คีย์บอร์ดในหนึ่งในของฉันEditTextsและกิจกรรมสูญเสียโฟกัส

สิ่งที่ฉันทำคือซ่อนแป้นพิมพ์ใน onPause ();

@Override
protected void onPause() {

    // hide the keyboard in order to avoid getTextBeforeCursor on inactive InputConnection
    InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    inputMethodManager.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

    super.onPause();
}

2
นี่คือคำตอบที่ถูกต้อง ตรวจสอบให้แน่ใจว่าคุณได้ซ่อนแป้นพิมพ์ก่อนที่คุณจะออกจากกิจกรรมที่คุณมีอยู่บนหน้าจอ
Gábor

1

แก้ไขปัญหานี้ด้วยตัวเองบางทีคุณอาจมีปัญหาเดียวกัน

สิ่งนี้เกิดจากObjectในHeaderViewของList Adapterรายการอะแดปเตอร์

ฉันขยายมุมมองและประกาศวัตถุและวางTextWatcherไว้

View v = LayoutInflater.from(CONTEXT).inflate(R.layout.in_overscrollview, null);
Object= (Object) v.findViewById(R.id.OBJECT_ID);

Object.addTextChangedListener(new TextWatcher() {
        @Override
        public void afterTextChanged(Editable s) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        //Do my work
        //Update my view
        }
});

เพิ่มลงในList Adapterและสร้างอะแดปเตอร์

JobListView = (ListView) getListView().findViewWithTag("JOBLISTVIEWTAG");
JobListView.addHeaderView(v, null, false);
JobsAdapter = new IN_JOBS_ADAPTER(CONTEXT, ITEMS_FOR_ADATER);
ListView.setAdapter(JOBSadapter);

ทุกอย่างเรียบร้อยดีText Watcher ใช้งานได้

แต่ถ้าฉันสร้างอะแด็ปเตอร์ใหม่หลังจากสร้างครั้งแรก

JobsAdapter = new IN_JOBS_ADAPTER(CONTEXT, DIFFERENT_ITEMS_FOR_ADAPTER);
ListView.setAdapter(JOBSadapter);

HeaderViewนั้นจะสร้างใหม่เกินไป

คำเตือนนั้นจะแสดงขึ้นเนื่องจากอ็อบเจ็กต์ถูกลบออกและ Text Watcher ยังคงถูกตั้งค่าให้เฝ้าดูอยู่

ตัวแปลงรายการและวัตถุถูกแทนที่และฉันเดาว่าText Watcherกำลังมองหาวิธีอื่นเมื่อมันเกิดขึ้น

ดังนั้นคำเตือนจึงดับลงและText WatcherพบHeaderViewและObject ได้อย่างน่าอัศจรรย์ได้แต่มันสูญเสียโฟกัสและบันทึกคำเตือนนั้น

การใช้

JOBSadapter.notifyDataSetChanged();

แก้ไขปัญหา

แต่ถ้าคุณมีObjectอยู่ในAdapterและText Watcherติดอยู่กับObjectภายในAdapterอะแดปเตอร์จากนั้นคุณอาจต้องทำงานเพิ่มอีกเล็กน้อย

ลองถอด Listener ออกแล้วแนบอีกครั้งหลังจากทำงานอะไรก็ได้ที่คุณกำลังทำอยู่

Object.removeTextChangedListener();

หรือ

Object.addTextChangedListener(null);

1

นอกเหนือจากคำตอบของ antoniom แล้วโปรดตรวจสอบให้แน่ใจว่าการดำเนินการเพิ่มเติมใด ๆ ที่จำเป็นต้องทำเสร็จสิ้นหลังจากซ่อนแป้นพิมพ์แล้วดังนั้นหากคุณซ่อนแป้นพิมพ์ดังที่แสดงด้านล่าง:

public void hideKeyboard() {
InputMethodManager inputMethodManager =(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}

คุณต้องดำเนินการให้สำเร็จโพสต์การซ่อนแป้นพิมพ์ดังนี้:

getWindow().getDecorView().post(new Runnable() {            
        @Override
        public void run() {
            finish(); //Sample succeeding code
     }
});

0

ฉันมีปัญหานี้เมื่อฉันต้องแก้ไขหรือรับข้อความจาก EditText และมันถูกโฟกัส

ดังนั้นก่อนที่จะแก้ไขหรือรับจากมันฉันปิดแป้นพิมพ์และแก้ไข

InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

บางทีปัญหาของคุณอาจแตกต่างกัน


0

ฉันได้แก้ไขปัญหาของฉันในการแทรกประเภทอินพุตบน xml เช่นนี้: android: inputType = "none | text | textCapWords | textUri"

ก่อนหน้านั้นคือ android: inputType = "text" สิ่งนี้ช่วยแก้ปัญหาของฉันได้


3
ไม่ได้ทำอะไรให้ฉัน
DSlomer64

0

ข้อผิดพลาดใน Logcat: getTextBeforeCursor บน InputConnection ที่ไม่ใช้งาน

วิธีแก้ไข: ซ่อนแป้นพิมพ์ป้อนข้อมูลของคุณและเรียกใช้แอปพลิเคชัน


0

ซ่อนแป้นพิมพ์ซอฟต์แวร์ก่อนล้าง EditText - คำเตือนจะไม่แสดง

นอกจากนี้มันน่าจะเป็นเฉพาะอุปกรณ์ ฉันเคยเห็นบน Nexus 4 (Android 7.1) เท่านั้น ไม่มีคำเตือนเกี่ยวกับอีมูเลเตอร์ (8.0, 7.1) หรือ Nexus 5


0

ปัญหาของฉันเกิดจากการตั้งค่าการมองเห็นของEditTextถึงGONEแล้วตั้งค่าเป็นVISIBLEทุกครั้งที่ผู้ใช้พิมพ์อักขระขณะที่ฉันกำลังเรียกใช้การตรวจสอบความถูกต้องของอินพุตทุกครั้งที่ข้อความเปลี่ยนไปและในบางกรณีจำเป็นต้องซ่อนมุมมอง

ดังนั้นวิธีแก้ปัญหาคือหลีกเลี่ยงการตั้งค่าการมองเห็นของ View หรือ Layout เป็น GONE ระหว่าง UI หรือการอัปเดตสถานะเนื่องจากEditTextอาจสูญเสียโฟกัส


0

iface ปัญหาเดียวกันและแก้ไขโดยการแปลงวิดเจ็ต stateless ของฉันเป็นวิดเจ็ต statefull คุณสามารถลองใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.