为什么我的Android Adapter没有getActivity()方法

时间:2017-07-26 19:40:21

标签: android

为什么我的Android Adapter没有getActivity()方法?然而,许多教程可以访问内部的getActivity()方法,让我们说回收器视图适配器

我已经尝试使用构造函数从片段传递getActivity()但仍然没有完成我想要的。

My Fragment调用适配器

package layout;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import com.example.elm.login.Navigation;
import com.example.elm.login.R;
import com.example.elm.login.adapter.NotesAdapter;
import com.example.elm.login.model.Note;
import com.example.elm.login.services.note.UploadNote;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link NotesFragment.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link NotesFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class NotesFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public List<Note> notes = new ArrayList<>();
private RecyclerView recyclerView;
public NotesAdapter notesAdapter;

public NotesFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment NotesFragment.
 */
// TODO: Rename and change types and number of parameters
public static NotesFragment newInstance(String param1, String param2) {
    NotesFragment fragment = new NotesFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

private UploadReceiver receiver;
private SyncReceiver syncReceiver;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_notes2, container, false);

    //register broadcast receiver
    IntentFilter filter = new IntentFilter(UploadNote.ACTION_RESP);
    //filter.addCategory(Intent.CATEGORY_DEFAULT);
    receiver = new UploadReceiver();
    getActivity().registerReceiver(receiver, filter);

    IntentFilter intentFilter = new IntentFilter(SyncReceiver.SYNC_ACTION);
    syncReceiver = new SyncReceiver();
    getActivity().registerReceiver(syncReceiver, intentFilter);

    recyclerView = (RecyclerView) view.findViewById(R.id.notes_recycler);
    notes = Note.find(Note.class, null,null,null,"noteid DESC", null);

    notesAdapter = new NotesAdapter(notes);

    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    recyclerView.setAdapter(notesAdapter);


    return  view;
    //return inflater.inflate(R.layout.fragment_notes2, container, false);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}



 /* @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

*/

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

@Override
public void onResume() {
    super.onResume();

}

/**
 * redraw the recycler -view --all of it
 */

public void addNew(Note note){
    if (notesAdapter!=null){
        notesAdapter.newData(note);
        recyclerView.smoothScrollToPosition(0);

    }
}

public void update(Note note){
    if (notesAdapter!=null){
        notesAdapter.updateItem(note);
    }
}

/**
 * receive broadcasts
 */
public class UploadReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("vane", "vane");
        Bundle bundle = intent.getExtras();
        String newNote = bundle.getString("note");
        Gson gson = new Gson();
        Type type = new TypeToken<Note>(){
        }.getType();
        Note note = gson.fromJson(newNote, type);
        addNew(note);

    }
}
public class SyncReceiver extends BroadcastReceiver{
    public static final String SYNC_ACTION = "sync_action";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("received_sync", "yes");
        Bundle bundle = intent.getExtras();
        String newNote = bundle.getString("note");
        Gson gson = new Gson();
        Type type = new TypeToken<Note>(){
        }.getType();
        Note note = gson.fromJson(newNote, type);
        update(note);

    }
}

}

和我的适配器:我无法声明getActivity方法的实例。

package com.example.elm.login.adapter;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback;
import com.bignerdranch.android.multiselector.MultiSelector;
import com.bignerdranch.android.multiselector.SwappingHolder;
import com.example.elm.login.FullNote;
import com.example.elm.login.Navigation;
import com.example.elm.login.R;
import com.example.elm.login.model.Note;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by elm on 7/17/17.
 */

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.myViewHolder> {
    private Context context;
    public List<Note> allnotes;
    private MultiSelector multiSelector = new MultiSelector();
    private ModalMultiSelectorCallback modalMultiSelectorCallback = new ModalMultiSelectorCallback(multiSelector) {
        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
            return super.onCreateActionMode(actionMode, menu);
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
    }
};

public NotesAdapter(List<Note> allnotes) {
    this.allnotes = allnotes;
}

@Override
public NotesAdapter.myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.activity_note_card, parent, false);
    return new myViewHolder(view);
}

@Override
public void onBindViewHolder(NotesAdapter.myViewHolder holder, int position) {
    //context = holder
    Note notes = allnotes.get(position);
    holder.title.setText(notes.getTitle());
    holder.note.setText(notes.getNote());
    if (notes.getUploadflag()){
        holder.imageView.setImageResource(R.mipmap.ic_cloud);
    }else {
        holder.imageView.setImageResource(R.mipmap.ic_cloud_done);
    }
}

@Override
public int getItemCount() {
    return allnotes.size();
}

public class myViewHolder extends SwappingHolder{
    public TextView title, note;
    public ImageView imageView;

    public myViewHolder(View itemView) {
        super(itemView, multiSelector);
        title = (TextView) itemView.findViewById(R.id.card_title);
        note = (TextView) itemView.findViewById(R.id.card_note);
        imageView = (ImageView) itemView.findViewById(R.id.uploadstatus);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = getLayoutPosition();
                Note note = allnotes.get(pos);
                Intent intent = new Intent(v.getContext(), FullNote.class);
                intent.putExtra("noteId", note.getId());
                v.getContext().startActivity(intent);
            }
        });

        itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {

                if (!multiSelector.isSelectable()){
                    ((AppCompatActivity) v.getContext()).startSupportActionMode(modalMultiSelectorCallback);
                    multiSelector.setSelectable(true);
                    multiSelector.setSelected(myViewHolder.this, true);
                    return true;
                }
                return false;
            }
        });
    }
}

public void swapAll(List<Note> notes){
    allnotes.clear();
    allnotes.addAll(notes);
    this.notifyDataSetChanged();
}

public void newData(Note note){
    this.allnotes.add(0, note);
    notifyItemInserted(0);
    notifyItemRangeChanged(0, allnotes.size());
}

public void updateItem(Note note){
    Log.e("atview", String.valueOf(note.getId()));
    Note data = null;
    for (Note n: allnotes){
        Log.e("id", String.valueOf(n.getId()));
        if (n.getId().equals(note.getId())){
            Log.e("found", String.valueOf(allnotes.indexOf(n)));
            int position = allnotes.indexOf(n);

            allnotes.remove(position);
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, allnotes.size());

            allnotes.add(position, note);
            notifyItemInserted(position);
            notifyItemRangeChanged(position, allnotes.size());


            break;
        }
    }
}

public void removeItem(int position){
    allnotes.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, allnotes.size());
}

}

7 个答案:

答案 0 :(得分:9)

您可以将Context传递给适配器,但是您无法从内部类访问getActivity()方法。

添加方法,或将Context作为参数放在构造函数中:

addContext(Context context);

初始化适配器时,您可以调用新方法

myAdapter.addContext(MyActivity.this);

如果要调用特定于活动的方法(即refreshViews()方法),可以检查类并使用强制转换:

if (context.getClass().equals(MyActivity.class)) {
    ((MyActivity) context).refreshView();
}

编辑::  完成适配器后,请务必清除对上下文的引用,以避免内存泄漏。

答案 1 :(得分:2)

它没有它,因为Context内部没有使用Adapter。当您需要特定应用程序范围的副作用或资源检索时,将使用Context

当您在Context内找到使用Adapter的代码时,您会注意到它使用Context来创建View,从中获取资源XML文件(即strings.xml)或某些提供实用程序的工厂。这些代码示例是为了提供清晰度而编写的。

实际的Adapter实现者​​应该知道这些用例并通过从Context的实例化器中获取Adapter或通过编写她自己的间接来实现自己的解决方案检索资源和/或实用程序。

实现这一目标的一种简单方法是使用返回Context的单个方法定义接口。

interface ContextProvider {
    Context getContext();
}

然后,无论谁分配您的Adapter新用户(即ActivityFragment),都可以通过提供商界面转发其Context

// Your MyActivity.java or MyFragment.java
MyAdapter anAdapter = new MyAdapter(new ContextProvider {
    @Override
    public Context getContext() {
        return getActivity(); // For fragments
        return MyActivity.this; // For activities
    }
});

// MyAdapter.java
class MyAdapter extends SomeAdapterFromSDK {
    private final ContextProvider mContextProvider;

    public MyAdapter(ContextProvider cp) {
        mContextProvider = cp;
    }

    public void someAdapterMethod() {
        Context c = mContextProvider.getContext();
        // Use c as your context (i.e c.getString(R.string.message))
    }
}

巨大的免责声明:不要像Context那样直接通过new Adapter(getActivity())。当您的应用返回主屏幕时,由于将其保留在属性中,它会泄漏。

答案 2 :(得分:0)

只有片段对象才能调用getActivity()。如果您可能遇到过在适配器中使用getActivity()的教程,我认为他们试图传达的是用活动参考替换getActivity()。

来自android开发者documentation

  

活动getActivity()   返回此片段当前与之关联的活动。

答案 3 :(得分:0)

notesAdapter = new NotesAdapter(notes, getActivity());

然后在适配器中使用该引用。

答案 4 :(得分:0)

您可以通过介绍它们之间的接口来访问活动的成员和方法。

interface ActivityInterface {
     public Context getPresentActivityContext();
}

在活动中,

Class Activity implements ActivityInterface {

      .....
      .....
      @Override
      public Context getPresentActivityContext() {
           return getApplicationContext();
      }
      .....
      .....
      adapter.setActivityInterface(this);
}

在适配器中,

private ActivityInterface activityInterface;

public void setActivityInterface(ActivityInterface activityInterface) {
     this.activityInterface = activityInterface;
}

在此之后,您可以使用适配器中的 activityInterface.getPresentActivityContext() 直接访问上下文。这不会创建任何内存引用。你可以避免内存泄漏。

答案 5 :(得分:0)

在 Adapter 中创建构造函数。

public NotesAdapter(List<Note> allnotes) {
    this.allnotes = allnotes;
}

Activity mActivity;
//....
public NotesAdapter(List<Note> allnotes,Activity mActivity) {
this.allnotes = allnotes;
this.mActivity = mActivity;
}

尝试在 NotesFragment 中更改

notesAdapter = new NotesAdapter(notes,getActivity());

答案 6 :(得分:-1)

通过创建像

这样的片段的静态实例来实现它的另一种方法
static NotesFragment note_instance;

和onCreate赋值

note_fragment=this;

您可以创建一个静态方法来获取像

这样的实例
public static NotesFragment getInstance (){
return note_fragment;
}

然后你可以对最近的片段实例做任何事情但是一定要检查实例是否为null以避免空指针异常 您可以通过

访问该方法
NotesFragment.getInstance();