【问题标题】:Can't access a variable in fragment from host activity无法从主机活动访问片段中的变量
【发布时间】:2016-06-02 17:49:15
【问题描述】:

在我的片段中,我正在从网络上获取一个字符串,并且我希望启用托管活动来获取此字符串,并在后台堆栈更改时使用它来设置其操作栏的副标题。 我关注this answer,正在使用第三个选项。

这是我的代码:

匹配活动

public class Match extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener{


    public String matchTitle



    public String getMatchTitle() {
        return matchTitle;
    }

    public void setMatchTitle(String matchTitle) {
        this.matchTitle = matchTitle;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

    //The usuals

    if (savedInstanceState == null) {
                Bundle bundle = new Bundle();
                Fragment fragment;

                fragment = new DetailsFragment();
                bundle.putString("match_link", news_id);
                fragment.setArguments(bundle);

                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.setCustomAnimations(android.R.anim.slide_out_right, android.R.anim.slide_in_left, android.R.anim.slide_out_right, android.R.anim.slide_in_left);
                ft.add(R.id.match_frame, fragment);
                ft.commit();
            }

            if (savedInstanceState != null) {
                mContent = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
            }
    }

    ....
    @Override
        public void onBackStackChanged() {
            String subtitle = getMatchTitle();
            mToolbar.setSubtitle(subtitle);
        }

        ...

DetailsFragment

公共类 DetailsFragment 扩展 Fragment {

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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView called");
    //The usuals
  }

        private void  getMatch() {
    Log.d(TAG, "getMatch called");
    String matchJson = GET_URL + matchID;
    JsonObjectRequest matchDetails = new JsonObjectRequest(Method.GET, matchJson, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    Log.d(TAG, "onResponse for getMatch called");
                    parseJson(response);
                    mainMatch = response;
                    if (progressBar != null) {
                        progressBar.setVisibility(View.GONE);
                    }
                }
            },
            new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d(TAG,  "onErrorResponse for getMatch called");
            if (progressBar != null) {
                progressBar.setVisibility(View.GONE);
            }
            if (sthWrongAlert != null) {
                sthWrongAlert.show();
            }
        }
    });


    //Creating requestqueue
    RequestQueue requestQueue = Volley.newRequestQueue(getActivity());

    //Adding request queue
    requestQueue.add(matchDetails);
}

private void parseJson(JSONObject object) {
    Log.d(TAG, "Parsing Json");
    try {
        final String title = String.valueOf(Html.fromHtml(object.getString("title")));
        matchTitle.setText(title);

            Match match = new Match();
            match.setMatchTitle(title);


    } catch (JSONException w) {
        w.printStackTrace();

    }
}

注意 我知道我可以轻松地从片段中设置字幕,但我不想这样做。我只是想确保我可以从它的宿主活动中访问片段中的变量。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    一种方法是在 Fragment 中定义一个接口,并让 Activity 实现该接口。例如:

    public class DetailsFragment {
        public interface OnTitleChangedListener {
            void onTitleChanged(String newTitle);
        }
    
        private OnTitleChangedListener mListener;
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            mListener = (OnTitleChangedListener) context;
            // TODO ensure instanceof OntTitleChangeListener
        }
    }
    

    然后,在您的凌空onResponse 回调中,调用mListener.onTitleChanged(newTitle) 将更改传达给活动。您的活动代码可能如下所示:

    public class MatchActivity implements DetailsFragment.OnTitleChangedListener {
        @Override
        public void onTitleChanged(String newTitle) {
             mToolbar.setSubtitle(newTitle);
        }
    

    【讨论】:

    • 您好,chessdork,谢谢您的回答。最初我按照您的建议进行操作,但实际发生的情况是,如果添加并添加了另一个 DetailsFragment 实例,则工具栏的标题将是从最后添加的 DetailsFragment。这就是为什么我希望 Activity 监听 backstack 中的变化,获取标题的当前值并使用它来设置 Activity 的副标题。
    • 我明白了。将工具栏放在片段中似乎更容易,因为标题取决于片段状态。
    • 是说我不能从它的父 Activity 访问片段中的变量吗?
    • 好吧,您总是可以在片段中定义一个公共 getter。说getTitle。然后在您的活动中,((DetailFragment) getFragmentManager().findFragmentByTag()).getTitle()。这里的问题是您想要其标题的 DetailFragment 正在更改。 getTitle 的结果取决于 Volley 请求是否完成。您可以尝试获取 backstack 上的最顶层片段,并通过您的公共 getter 访问标题。但这似乎比将工具栏放在 Fragment 中要困难得多。
    • 到目前为止,问题并不在于硬性解决方案。
    【解决方案2】:

    在 Activity 中直接从 Fragment 访问变量会在 Fragment 和宿主 Activity 之间引入强耦合。我建议使用诸如 otto、http://square.github.io/otto/ 之类的通信库来处理这两者之间的通信。您可以注册 Activity 以侦听 SubtitleChangeEvent,然后在需要反映字幕更改时从片段中触发此事件。

    【讨论】:

      猜你喜欢
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多