【问题标题】:Android Programming - Fragments and ListenersAndroid 编程 - 片段和监听器
【发布时间】:2014-05-17 02:11:46
【问题描述】:

我正在关注互联网上的教程,我必须为我的按钮制作一个监听器。我正在观看的教程与我的代码非常不同,即使该视频是在一年前发布的。我正在观看的视频中没有“片段”代码。在我的代码中,我的 MainActivity.java 中有一个片段。什么是片段?在我的 mainactivity.java 接近尾声时,我得到了这个:

public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        button1 = (Button)rootView.findViewById(R.id.button1);
        button2 = (Button)rootView.findViewById(R.id.button2);
        button3 = (Button)rootView.findViewById(R.id.button3);

        button1.setOnClickListener(listener);
        button2.setOnClickListener(listener);
        button3.setOnClickListener(listener);

        return rootView;
    }
}

谁能向我解释一下占位符片段是什么?这是我的代码。我在这里遇到错误:

ERROR: "Toast.makeText(MainActivity.this, "toast", Toast.LENGTH_SHORT);"
Message: "No enclosing instance of the type MainActivity is accessible in scope"

。 私有静态 OnClickListener 监听器 = 新 OnClickListener() { @覆盖 公共无效 onClick(查看 v){ int id = v.getId();

        switch(id)
        {
        case R.id.button1:
            Toast.makeText(MainActivity.this, "toast", Toast.LENGTH_SHORT);
            break;
        case R.id.button2:
            break;
        case R.id.button3:
            break;
        default:
            break;
        }
    }
};

这是我的完整代码(MainActivity.java):

package com.example.androiddevelopmentonline_part2_1;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

private static Button button1, button2, button3;

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

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment())
                .commit();
    }
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}


private static OnClickListener listener = new OnClickListener()
{
    @Override
    public void onClick(View v) {
        int id = v.getId();

        switch(id)
        {
        case R.id.button1:
            Toast.makeText(MainActivity.this, "toast", Toast.LENGTH_SHORT);
            break;
        case R.id.button2:
            break;
        case R.id.button3:
            break;
        default:
            break;
        }
    }
};

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        button1 = (Button)rootView.findViewById(R.id.button1);
        button2 = (Button)rootView.findViewById(R.id.button2);
        button3 = (Button)rootView.findViewById(R.id.button3);

        button1.setOnClickListener(listener);
        button2.setOnClickListener(listener);
        button3.setOnClickListener(listener);

        return rootView;
    }
}
}

【问题讨论】:

    标签: android listeners


    【解决方案1】:

    最好的解释可能在开发者文档中(这里:https://developer.android.com/guide/components/fragments.html

    这是“QuickView”中的一些内容

    Fragments decompose application functionality and UI into reusable modules
    Add multiple fragments to a screen to avoid switching activities
    Fragments have their own lifecycle, state, and back stack
    Fragments require API Level 11 or greater
    

    我解释它的方式是,它是 UI 的可重用组件,具有自己的生命周期。它用于将您的 UI 分解为(多个)、更加独立且符合逻辑的“部分”。

    在您的情况下,我认为您的 IDE 已自动为您生成代码并生成 PlaceholderFragment。正如它所说,一个自动生成的占位符。如果你现在只使用Activities,你可以摆脱它。但最好稍后再查看 Fragment 教程,因为它们在较新版本的 android 中经常使用(Fragment 不是必需的,但它们是一种“更好的做法”,具体取决于您的应用程序架构)。

    您收到错误的原因:

    错误:“Toast.makeText(MainActivity.this, "toast", Toast.LENGTH_SHORT);"

    消息:“范围内没有 MainActivity 类型的封闭实例可访问”

    实际上在消息中进行了解释。您已将 OnClickListener 声明为匿名的 static 属性。因为它是static,所以它不能访问类的当前实例(它“不在范围内”,它不能访问非静态方法和属性)。要修复它,只需删除 static 关键字:

    private OnClickListener listener = new OnClickListener() //... etc
    

    有关 Java 中 static 关键字的说明,请查看此处:http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.htmlWhat does the 'static' keyword do in a class?

    EDIT(一种更简洁的实现 OnClickListener 的方式)

    一个更好的主意是将您的OnClickListener 放在您的PlaceholderFragment 中(因为这是使用它的地方),或者让您的PlaceholderFragment 实现View.OnClickListener(我更喜欢这种方式,减少匿名类型,它编码格式更好,但这是一个偏好问题)。一个例子(寻找 cmets):

    // note, doesn't matter if it is static
    // I got rid of the OnClickListener attribute and made PlaceholderFragment implement OnClickListener like so
    public static class PlaceholderFragment extends Fragment implements OnClickListener
    {
        // No need to provide a constructor. Fragments by default should have an empty constructor. If you want to add data to it, you need to create a "newInstance" method which calls fragment.setArguments (SomeBundleWithValuesInIt)
        @ Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState)
        {
            View rootView = inflater.inflate (R.layout.fragment_main, container, false);
    
            button1 = (Button) rootView.findViewById (R.id.button1);
            button2 = (Button) rootView.findViewById (R.id.button2);
            button3 = (Button) rootView.findViewById (R.id.button3);
    
            // I set the OnClickListener to the PlaceholderFragment itself, because it implements OnClickListener (which is an interface), you can use it this way.
            button1.setOnClickListener (this);
            button2.setOnClickListener (this);
            button3.setOnClickListener (this);
    
            return rootView;
        }
    
        // OnClickListener.onClick(View) moved here.
        @ Override
        public void onClick(View v)
        {
            int id = v.getId ();
    
            switch (id) {
                case R.id.button1 :
                    // getActivity() can be used instead of Context (Activity is one of the subclasses of Context), but only within a Fragment in this case
                    Toast.makeText (getActivity (), "toast", Toast.LENGTH_SHORT);
                    break;
                case R.id.button2 :
                    break;
                case R.id.button3 :
                    break;
                default :
                    break;
            }
        }
    }
    

    【讨论】:

    • 谢谢!但现在当我尝试添加监听器时。例如 button1.setOnClickListener(listener);我收到一条错误消息,说它不能对非静态字段进行静态引用。每当我删除片段并将我的代码移动到 on create 方法时也是如此。该应用程序无法启动。非常感谢@AniFichadia
    • @user3453481 哦,抱歉,之前没有意识到。它与您的OnClickListenerPlaceholderFragment 基本相同,只需删除static。我会更新我的答案,因为有更好的方法来代替使用 MainActivity.this,这意味着将您的 OnClickListener 放入 PlaceholderFragment 并在使用 Fragment.getActivity() 通知时使用 Fragment.getActivity()
    • @user3453481,我还要提一下,如果您从PlaceholderFragment 中删除静态,则意味着PlaceholderFragment“属于”MainActivity,因此它可以访问其所有属性和方法,而无需错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    • 2019-05-27
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多