适配器类中的super.onActivityResult?安卓

Posted

技术标签:

【中文标题】适配器类中的super.onActivityResult?安卓【英文标题】:super.onActivityResult inside adapter class? Android 【发布时间】:2016-03-24 06:46:33 【问题描述】:

我的 RecyclerView 包含非常复杂的项目、多个按钮/图像/文本。 要访问每个按钮/图像,我在 Adapter 类中设置了单击侦听器。

但现在我正在尝试添加设置联系人铃声的功能,但我遇到了问题。

我这样调用 onActivityResult 方法:

Intent contactIntent = new Intent(Intent.ACTION_PICK);
                contactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
                contactIntent.putExtra("ITEM_POSITION", position);
                ((Activity) context).startActivityForResult(contactIntent, CONTACT_CHOOSER_ACTIVITY_CODE );

而且效果很好。 但问题来了:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) 
....
...
...


我收到此错误:Cannot resolve method 'onActivityResult(int, int, android.content.Intent)' 有没有办法避免这种情况?或者是否可以在适配器类中使用此方法?如果不是我该怎么办?

【问题讨论】:

你使用什么类型的适配器? 我正在使用RecyclerView.Adapter 我添加了一个非常简单的示例,向您展示您应该做什么 @inner_class7 哇! :O 它有效!谢谢 【参考方案1】:

你不能在任何 Adapter 类中拥有这个,这只是 Activity 内部的一个方法,extends Activity 的每个类都可以覆盖这个方法,但肯定不是 Adapter。

请在java中查看Overrides

对于onActivityResult,请参阅Activity#onActivityResult(int, int, Intent)

对于像RecyclerView.Adapter 这样的东西,您需要在适配器中定义一个接口并在您的 Activity 中实现该接口。

例如,这里是一个应用程序的代码,它将一个被点击的项目及其位置的字符串发送到一个显示它的新活动:

主活动:

public class MainActivity extends AppCompatActivity implements MyAdapter.CallbackInterface 


    private static final int MY_REQUEST = 1001;

    private static final String [] ITEMS = "Item 1", "Item 2", "Item 3" ,"Item 4", "Item 5", "Item 6";

    private MyAdapter myAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ... Adapter setup, simple LinearLayoutManager and String [] used
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rec_view);
        myAdapter = new MyAdapter(this, ITEMS);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(myAdapter);
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);
        switch(resultCode)

            case RESULT_OK:

                // ... Check for some data from the intent
                if(requestCode == MY_REQUEST)
                    // .. lets toast again
                    int position = -1;
                    if(data != null)
                        position = data.getIntExtra("Position", 0);
                    

                    if(position != -1) 
                        Toast.makeText(this, "Handled the result successfully at position " + position, Toast.LENGTH_SHORT).show();
                    else
                        Toast.makeText(this, "Failed to get data from intent" , Toast.LENGTH_SHORT).show();
                    
                

                break;

            case RESULT_CANCELED:

                // ... Handle this situation
                break;
        
    

    /**
     * Interface Method which communicates to the Acitivty here from the @link MyAdapter
     * @param position - the position
     * @param text - the text to pass back
     */
    @Override
    public void onHandleSelection(int position, String text) 

        Toast.makeText(this, "Selected item in list "+ position + " with text "+ text, Toast.LENGTH_SHORT).show();

        // ... Start a new Activity here and pass the values
        Intent secondActivity = new Intent(MainActivity.this, DetailActivity.class);
        secondActivity.putExtra("Text",text);
        secondActivity.putExtra("Position", position);
        startActivityForResult(secondActivity, MY_REQUEST);
    

MainActivity 的xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.divshark.recyclerviewsimpledemo.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:layout_
        android:layout_
        android:id="@+id/rec_view" />
</RelativeLayout>

我的适配器:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>

    private CallbackInterface mCallback;
    private String [] mMyItems;
    private Context mContext;

    public interface CallbackInterface

        /**
         * Callback invoked when clicked
         * @param position - the position
         * @param text - the text to pass back
         */
        void onHandleSelection(int position, String text);
    

    public MyAdapter(Context context, String [] myItems)

        mContext = context;
        mMyItems = myItems;

        // .. Attach the interface
        try
            mCallback = (CallbackInterface) context;
        catch(ClassCastException ex)
            //.. should log the error or throw and exception
            Log.e("MyAdapter","Must implement the CallbackInterface in the Activity", ex);
        
    

    @Override
    public int getItemCount() 
        return mMyItems.length;
    

    @Override
    public long getItemId(int position) 
        return position;
    

    @Override
    public void onBindViewHolder(MyHolder holder, final int position) 

        // Set the text for the View
        holder.mTextView.setText(mMyItems[position]);

        // Use your listener to pass back the data
        holder.itemView.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                if(mCallback != null)
                    mCallback.onHandleSelection(position, mMyItems[position]);
                
            
        );
    

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) 

        View view = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
        return new MyHolder(view);
    

    static class MyHolder extends RecyclerView.ViewHolder

        TextView mTextView;

        public MyHolder(View itemView) 
            super(itemView);

            mTextView = (TextView) itemView.findViewById(R.id.tv_list_item);
        
    

适配器的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" android:layout_
    android:layout_>

    <TextView
        android:id="@+id/tv_list_item"
        android:textColor="@android:color/black"
        tools:text="Some Text Holder"
        android:layout_marginLeft="16dp"
        android:textSize="18sp"
        android:layout_centerVertical="true"
        android:layout_
        android:layout_ />
</RelativeLayout>

和 DetailActivity:

public class DetailActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.detail_activity);

        TextView textView = (TextView) findViewById(R.id.tv_detail_text);

        if(getIntent() != null && getIntent().getExtras() != null) 
            Bundle extras = getIntent().getExtras();
            String text = extras.getString("Text");
            int position = extras.getInt("Position");

            textView.setText(String.format("%s at position %d", text, position));

            // .. For this purpose set result okay and use position as part of data when Activity finishes
            // Which will in turn invoke the onActivityResult method in the calling activity
            Intent resultIntent = new Intent();
            resultIntent.putExtra("Position", position);
            setResult(RESULT_OK, resultIntent);
        
    

详细活动的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_ android:layout_>


    <TextView
        android:id="@+id/tv_detail_text"
        android:layout_gravity="center"
        android:layout_
        android:layout_ />
</FrameLayout>

祝你好运,编码愉快!

【讨论】:

有什么我可以做的吗?没有将整个点击侦听器移动到某个活动类?【参考方案2】:

另一种解决方案是在您启动 RecyclerView/ListView 的活动类中设置 onActivityResult 方法。这也有效,除了由于某种原因我在尝试使用意图传递数据时遇到 NPE 错误,因此解决方法是创建静态 String/Int 并在点击和访问时更改它的值。这工作得很好。 但是上面的答案也很棒,而且在性能方面也同样出色,甚至可能更好。

【讨论】:

【参考方案3】:

我不知道你为什么需要从适配器类调用 onActivityResult() 方法。

无论如何最好的解决方案是从 adpater 类 startActivityForResult() 并通过指定请求代码和结果代码来监听 onActivityResultFrom() 活动类

【讨论】:

以上是关于适配器类中的super.onActivityResult?安卓的主要内容,如果未能解决你的问题,请参考以下文章

适配器类中的super.onActivityResult?安卓

如何在按钮单击时获得适配器类中的点击列表项位置

特征类中的成员函数“名称”? (通用适配器)

Android - 如何使用适配器类中的代码在布局文件中设置图像?

InvocationTargetException 在适配器类中膨胀视图

从片段类中的对话框添加项目到recyclerview。