如何在适配器类中调用 Main Activity 方法

Posted

技术标签:

【中文标题】如何在适配器类中调用 Main Activity 方法【英文标题】:How can I call Main Activity Method in adapter class 【发布时间】:2021-12-01 17:44:03 【问题描述】:

这是我的MainActivity,我在其中定义了dataRefresh 方法,该方法在从数据库中插入或删除数据时刷新适配器

public class MainActivity extends AppCompatActivity 
EditText phone, name;
ListView list;
MyDatabase db;
CustomAdapter ad;
ArrayList<contact> cont;
Button add;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    list=findViewById(R.id.list_item);
    db=new MyDatabase(this);
    cont=new ArrayList<>();
    cont=db.showData();
    ad=new CustomAdapter(this,cont;
    list.setAdapter(ad);



 public  void  dataRefresh()
    cont.clear();
    cont.addAll(db.showData());
    ad.notifyDataSetChanged();

上面是dataRefresh方法

这是我的适配器类,我调用删除方法从数据库中删除数据

    public class CustomAdapter extends ArrayAdapter 
    ArrayList<contact> phnecontact;
    MyDatabase db;
    LinearLayout horizon;
    Context context;

    public CustomAdapter(@NonNull Context context, ArrayList<contact> 
    phonecontact) 
    super(context,R.layout.customlayout,phonecontact);
    this.context = context;
    this.phnecontact = phonecontact;
    

    public contact getItem(int position) 
    return phnecontact.get(position);
   

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

  @NonNull
  @Override
  public View getView(int position, View i, ViewGroup parent) 
    View view = 
  LayoutInflater.from(context).inflate(R.layout.customlayout, parent, 
  false);
    contact s1 = phnecontact.get(position);
    db=new MyDatabase(context);
    TextView name=view.findViewById(R.id.cmname);
    horizont=view.findViewById(R.id.horizontal);
    TextView number=view.findViewById(R.id.cmphone);
    ImageView sms=view.findViewById(R.id.message);
    ImageView call=view.findViewById(R.id.phone);
    ImageView photo=view.findViewById(R.id.cmphoto);
    number.setText(String.valueOf(s1.getPhone()));
    name.setText(s1.getName());
    horizont.setOnLongClickListener(v -> 
       AlertDialog.Builder builder=new AlertDialog.Builder(context);
       builder.setTitle("Are you sure to delete");
       builder.setPositiveButton("yes", new 
       DialogInterface.OnClickListener() 
           @Override
           public void onClick(DialogInterface dialog, int which) 
               int i =db.Deletioncontact(s1.getPhone());

我想在if条件之后调用Mainactivity的dataRefresh方法

               if(i==1)
               

                   Toast.makeText(context, "contact is deleted", 
      Toast.LENGTH_SHORT).show();
               
               else
               
                   Toast.makeText(context, "contact not deleted", 
  Toast.LENGTH_SHORT).show();
               
           
       );

如果我使用 Mainactivity 的对象调用此方法,那么我的应用程序将崩溃

【问题讨论】:

您应该使用来自适配器的回调;参考链接:callback-from-dapter 如果他可以直接在适配器中初始化数据而不是他的方法,为什么要使用回调?我会在适配器的构造函数中加载数据。然后,您可以使用正确的通知方法实现 onItemAdded、onItemRemoved、...。然后你调用 adapter.onItemAdded,... @JohnDoe 这会使适配器类与活动紧密耦合,这不是一个好的编程方式。 回调对架构更友好,但在您的情况下,一个简单的解决方案是使用视图持有者视图中的上下文并通过您的活动进行投射,然后您可以调用您的活动方法。跨度> 【参考方案1】:

除了在mainActivity 中调用方法之外,还有一些可以改进的地方。

您不必在适配器中传递context,要在getView() 方法中使用,您可以从parent viewGroup 获取上下文

@Override
  public View getView(int position, View i, ViewGroup parent) 
    View view = 
  LayoutInflater.from(parent.getContext()).inflate(R.layout.customlayout, parent, 
  false);

您可以将所有clickListenerslongClickListeneners 逻辑移动到activity,并使用interface 来触发这些方法。这样,您的适配器类将与您的activity 松散耦合,您也可以在另一个activityfragment 中使用此adapter

在您的适配器类中创建clickInterface

public interface ClickListeners 
     public void onItemlongClickListener(int phone);

现在在你的活动中覆盖这个interface

public class MainActivity extends AppCompatActivity implements CustomAdapter.ClickListener
    //

    @Override
    protected void onCreate(Bundle savedInstanceState) 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         //
         ad = new CustomAdapter(this, cont); // pass interface instance to the adapter
         //
    

    @Override
    public void onItemlongClickListener(int phone) 
        // add your dialog confirmation 
        // and item deletion code here
    


更改CustomAdaper构造函数以获取接口实例

public CustomAdapter(ClickListeners clickListeners, ArrayList<contact> 
    phonecontact) 
    super(context,R.layout.customlayout,phonecontact);
    this.clickListeners = clickListeners;
    this.phnecontact = phonecontact;
    

当用户长按项目时触发onItemlongClickListener

horizon.setOnLongClickListener(v -> 
      clickListeners.onItemlongClickListener(s1.getPhone()); // call interface method

【讨论】:

【参考方案2】:

**在你的 onclick 方法中试试这个**

public void onClick(DialogInterface dialog, int which) 

int i =db.Deletioncontact(s1.getPhone());

Iterator<Integer> itr = numbers.iterator();
while(itr.hasNext())  
   Phone phone = itr.next(); 
   if (phone == s1.getPhone())   
      s1.remove(phone); 
    

notifyDataSetChange();

【讨论】:

以上是关于如何在适配器类中调用 Main Activity 方法的主要内容,如果未能解决你的问题,请参考以下文章

从适配器中的片段调用元素

如何从android中的自定义适配器调用Activity asynctask

如何在布局 activity_main(sw320dp) 中调用?

Android 中如何在java类中调用activity 中的一个方法?

如何更新适配器数据列表?

Android 如何从 Main Activity 中的另一个类调用 Activity 数据类型?