如何在类和使用它的片段之间进行通信?

时间:2018-06-20 19:43:39

标签: java android android-fragments

我正在使用Android Studio。我无法在线找到答案,因此即使是解决方案的链接也将很有帮助。

我有一个Activity,其中包含许多片段。这些片段之一称为BookGridFragment,它使用称为BookGrid的类。

BookGridFragment看起来像这样(我省略了无关的部分):

public class BookGridFragment extends Fragment {

    BookGrid myBookGrid;

    public BookGridFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        // Inflate layout
        View rootView = inflater.inflate(
                R.layout.fragment_book_grid, container, false);

        myBookGrid = rootView.findViewById(book_grid);

        return rootView;
    }

    public void setBook(Book thisBook) {
        myBookGrid.setBook(thisBook);
    }
}

BookGrid类是:

public class BookGrid extends View {

    private Book mBook;

    public BookGrid(Context thisContext, AttributeSet attrs) {
        super(thisContext, attrs);
    }

    public void setBook(Book newBook) {
        mBook = newBook;
    }

    protected void onDraw(Canvas canvas) {

        if (mBook == null) return; 

        canvas.save();

        draw_book_details(); 
        // draw_book_details() is a function which just takes 
        //  the book info and displays it in a grid

        canvas.restore();
    }

   public boolean onTouchEvent(MotionEvent event) {

       // This function responds to the user tapping a piece of
       //  book info within the grid

       // THIS IS WHERE I'M HAVING PROBLEMS
   }
}

所以,一切正常。问题是,我需要BookGridFragment知道用户何时触摸BookGrid并将该信息传递给另一个Fragment(通过Activity)。因此,我假设到达onTouchEvent时,应该以某种方式通知BookGridFragment BookGrid被触摸了,但是我不知道该怎么做。

我在网上找到的所有内容都是关于在片段之间传递信息,但是这种方法在这里行不通,因为BookGrid类并不“知道”它在BookGridFragment内。

5 个答案:

答案 0 :(得分:3)

您可以使用与传达片段和活动相同的想法。创建一个界面:

public interface OnBookGridTouched{
    void onTouchGrid();
} 

将变量添加到BookGrid:

private OnBookGridTouched mCallback;

向此变量添加一个setter:

public void setCallback(OnBookGridTouched callback){
    mCallback = callback;
}

然后使您的片段实现接口:

public class BookGridFragment extends Fragment implements OnBookGridTouched  {

您将被迫实施方法onTouchGrid

在片段的onCreateView中,将该片段传递到您的自定义视图:

myBookGrid.setCallback(this);

最后,在您的自定义视图中,您可以调用回调以引用该片段:

 public boolean onTouchEvent(MotionEvent event) {

       // This function responds to the user tapping a piece of
       //  book info within the grid

       // THIS IS WHERE I'M HAVING PROBLEMS
       mCallback.onTouchGrid();
   }

答案 1 :(得分:1)

一种解决方案是在片段中而不是BookGrid本身中设置onTouch / onClick侦听器。从那里,您可以使用片段方法getActivity()调用一个活动方法,将正确的数据解析为正确的片段。

答案 2 :(得分:1)

我认为这种情况与包含Fragment的{​​{1}}非常相似。

Button的方法可以接受实现特定接口的内容(对于ButtonButton)。 View.OnClickListener调用该方法(用于Button:Fragment)以传递所需的setOnClickListener()来实现所有必需的方法,这些方法可以是匿名类,也可以是字段或{{1} }本身。这三种方法各有利弊,这取决于您的情况,哪一种是最佳的。

他们的共同点是Object应该具有接口和方法,以便其他类可以设置当前的Fragment来实现该接口。

答案 3 :(得分:1)

我不太确定您在那里遇到的确切情况。但是,如果问题是片段与承载该片段的活动之间的通信,那么您可能会想到以下实现。

首先让我指出您的一些担忧。

  

我在网上找到的所有内容都是关于在   片段,但是这种方法在这里不能作为BookGrid类使用   不“知道”它在BookGridFragment中。

BookGrid类将在您调用其函数的同时向其传递Context时知道其存在的上下文。因此,我建议在从Activity类调用函数时,传递FragmentBookGrid的上下文。

public class BookGrid extends View {

    private Book mBook;
    private Context context;

    public BookGrid(Context thisContext, AttributeSet attrs) {
        super(thisContext, attrs);
        this.context = thisContext;
    }

    public void setBook(Book newBook) {
        mBook = newBook;
    }

    protected void onDraw(Canvas canvas) {

        if (mBook == null) return; 

        canvas.save();

        draw_book_details(); 
        // draw_book_details() is a function which just takes 
        //  the book info and displays it in a grid

        canvas.restore();
    }

   public boolean onTouchEvent(MotionEvent event) {
       // Call the function of your host activity
       ((YourActivity)(thisContext)).onBookGridTouched();
   }
}

现在在您的活动类中编写一个公共方法,该方法承载名为onBookGridTouched的片段。

public void onBookGridTouched() {
    // Communicate with other fragments here
}

但是,以更通用的方式解决此问题的一种崇高方法是使用interface,然后在需要时实施interface,如@LeviAlbuquerque建议的那样。

我只是提出了另一种解决方法,该解决方法有点静态。

答案 4 :(得分:1)

假设您有一个活动负责所有片段:

1。在BookGrid中创建一个接口:

public interface ActionHappened {
        void onActionHappened();
    }

2。在BookGrid类中创建接口的实例,然后在希望触发它的位置触发onActionHappened方法。例如,如果您希望它在onDraw()中发生,请执行以下操作:

ActionHappened actionHappened;

protected void onDraw(Canvas canvas) {

        if (mBook == null) return; 

        canvas.save();

        draw_book_details(); 
        // draw_book_details() is a function which just takes 
        //  the book info and displays it in a grid

        canvas.restore();

        actionHappened.onActionHappened();
    }

3。在活动中添加界面

public class ActivityA extends AppCompatActivity implements BookGrid.ActionHappened {}

4。在已实现的方法中,触发该方法:

@Override
public void onActionHappened() {
    Fragment fragmentA = getSupportFragmentManager().findFragmentByTag(R.id.fragmentA);
    Fragment fragmentB = getSupportFragmentManager().findFragmentByTag(R.id.fragmentB);

    //Trigger that method from your activity to fragmentA or fragmentB
    fragmentA.doWork();
    fragmentB.doWork();
}

无论您要将数据传递给fragmentA还是fragmentB,doWork()方法都可以为您完成。让您在相应的片段中创建这样的方法。