0

我在Android 可搜索字典示例应用程序中发现了有趣的错误。

请按照以下步骤重现它:

  • 在搜索框中输入“bo”
  • 点击去
  • 从结果中点击“虚假”
  • 当您看到结果和定义时,再次调用搜索
  • 输入“coa”,它应该给你“联盟”
  • 取而代之的是,什么也没有发生……

但这神奇地起作用:

  • 在搜索框中输入“bo”
  • 从自定义建议列表中选择虚假
  • 当您看到结果和定义时,再次调用搜索
  • 输入“coa”,它应该给你“联盟”
  • “联盟”真的找到了。

我想问你,为什么会出现这种情况以及如何修复它,所以它会正常运行。

这是一些有关主题的代码,我宁愿发布更多...

public class SearchableDictionary extends Activity {

private TextView mTextView;
private ListView mListView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mTextView = (TextView) findViewById(R.id.text);
    mListView = (ListView) findViewById(R.id.list);

    handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    // Because this activity has set launchMode="singleTop", the system calls this method
    // to deliver the intent if this activity is currently the foreground activity when
    // invoked again (when the user executes a search from this activity, we don't create
    // a new instance of this activity, so the system delivers the search intent here)
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        // handles a click on a search suggestion; launches activity to show word
        Intent wordIntent = new Intent(this, WordActivity.class);
        wordIntent.setData(intent.getData());
        startActivity(wordIntent);
    } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // handles a search query
        String query = intent.getStringExtra(SearchManager.QUERY);
        showResults(query);
    }
}

/**
 * Searches the dictionary and displays results for the given query.
 * @param query The search query
 */
private void showResults(String query) {

    Cursor cursor = managedQuery(DictionaryProvider.CONTENT_URI, null, null,
                            new String[] {query}, null);

    if (cursor == null) {
        // There are no results
        mTextView.setText(getString(R.string.no_results, new Object[] {query}));
    } else {
        // Display the number of results
        int count = cursor.getCount();
        String countString = getResources().getQuantityString(R.plurals.search_results,
                                count, new Object[] {count, query});
        mTextView.setText(countString);

        // Specify the columns we want to display in the result
        String[] from = new String[] { DictionaryDatabase.KEY_WORD,
                                       DictionaryDatabase.KEY_DEFINITION };

        // Specify the corresponding layout elements where we want the columns to go
        int[] to = new int[] { R.id.word,
                               R.id.definition };

        // Create a simple cursor adapter for the definitions and apply them to the ListView
        SimpleCursorAdapter words = new SimpleCursorAdapter(this,
                                      R.layout.result, cursor, from, to);
        mListView.setAdapter(words);

        // Define the on-click listener for the list items
        mListView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // Build the Intent used to open WordActivity with a specific word Uri
                Intent wordIntent = new Intent(getApplicationContext(), WordActivity.class);
                Uri data = Uri.withAppendedPath(DictionaryProvider.CONTENT_URI,
                                                String.valueOf(id));
                wordIntent.setData(data);
                startActivity(wordIntent);
            }
        });
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false);
    }

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.search:
            onSearchRequested();
            return true;
        default:
            return false;
    }
}
}

这个活动展示了结果:

public class WordActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.word);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    Uri uri = getIntent().getData();
    Cursor cursor = managedQuery(uri, null, null, null, null);

    if (cursor == null) {
        finish();
    } else {
        cursor.moveToFirst();

        TextView word = (TextView) findViewById(R.id.word);
        TextView definition = (TextView) findViewById(R.id.definition);

        int wIndex = cursor.getColumnIndexOrThrow(DictionaryDatabase.KEY_WORD);
        int dIndex = cursor.getColumnIndexOrThrow(DictionaryDatabase.KEY_DEFINITION);

        word.setText(cursor.getString(wIndex));
        definition.setText(cursor.getString(dIndex));
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false);
    }

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.search:
            onSearchRequested();
            return true;
        case android.R.id.home:
            Intent intent = new Intent(this, SearchableDictionary.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            return true;
        default:
            return false;
    }
}
}
4

1 回答 1

0

我想我已经弄清楚了错误。好吧,这不一定是错误,而只是实现它的不同方式。此实现使您只能ACTION_SEARCH在 SearchableActivity 中执行(非建议)。我也花了很多天才弄清楚这一点,因为它很难复制。它与 SearchableActivity 的 singleTop 启动模式有关。问题是,当您ACTION_SEARCH在 WordActivity 中使用(非建议)进行搜索时,它并没有按照它发送到 SearchableActivity onHandleIntentFLAG_ACTIVITY_CLEAR_TOP的意图进行设置。ACTION_SEARCH这会使您得到类似ActivityManager START SearchableActivity但从未出现的错误ActivityManager DISPLAY SearchableActivity。它永远不会进入onCreate()当发生此错误时,很难弄清楚如何解决它。为了解决这个问题,我认为您要么必须删除 singleTop 以使其在每次 ACTION_SEARCH 完成时创建另一个活动(并将handleIntent(Intent)方法调用放入onCreate()),要么覆盖onSearchRequested()startSearch(..., ..., ..., ...)方法以获取意图并设置意图标志。当然,如果您在使用 CLEAR_TOP 时点击了返回按钮,您将无法返回活动。我还没有弄清楚如何做后者,因为我不知道如何覆盖 startSearch 并获得意图:X

于 2013-07-15T16:05:05.397 回答