应该提供默认构造函数吗?

Should provide default constructor?

我有一个应用程序已转移到新的 android 工作室。当我尝试生成签名的 apk 时,出现此错误:

Error:(24) Error: This fragment should provide a default constructor (a public constructor with no arguments) (com.example.mike.beerportfolionewicon.BarcodeFrag) [ValidFragment]

class 是这样开始的:

public class BarcodeFrag extends Fragment implements ReadJSONResult.OnArticleSelectedListener {

    private ListView lv;
    View v;
    SearchView searchView;
    private SearchView mSearchView;
    private MenuItem mSearchMenuItem;
    String id;

    public BarcodeFrag(String scanContent) {
        id = scanContent;


    }

我选择了忽略检查的选项,但它仍然不会创建 apk...

尝试将其更改为此,但同样的错误:

public class BarcodeFrag extends Fragment implements ReadJSONResult.OnArticleSelectedListener {

    private ListView lv;
    View v;
    SearchView searchView;
    private SearchView mSearchView;
    private MenuItem mSearchMenuItem;
    String id;

    public BarcodeFrag(){}

    public BarcodeFrag(String scanContent) {
        id = scanContent;


    }

实际上是一个不同的错误:

Error:(35) Error: Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]

整个代码现在看起来像这样:

public class BarcodeFrag extends Fragment implements ReadJSONResult.OnArticleSelectedListener {

    private ListView lv;
    View v;
    SearchView searchView;
    private SearchView mSearchView;
    private MenuItem mSearchMenuItem;
    String id;

    public BarcodeFrag(){}

    public BarcodeFrag(String scanContent) {
        id = scanContent;


    }




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

        //set layout here
        v = inflater.inflate(R.layout.activity_search, container, false);
        setHasOptionsMenu(true);
        getActivity().setTitle("Search");


        //get user information
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        String userName = prefs.getString("userName", null);
        String userID = prefs.getString("userID", null);


        //run code with barcode content
        String url = "http://api.brewerydb.com/v2/search/upc?code="+ id +"&key=xxx&format=json&withBreweries=y";

        //run async task
        ReadJSONResult task = new ReadJSONResult(getActivity());
        task.setOnArticleSelectedListener(this);
        task.execute(url);




        return v;


    }

    @Override
    public void onArticleSelected(String b, String brewery){

        //code to execute on click
        Fragment Fragment_one;
        FragmentManager man= getFragmentManager();
        FragmentTransaction tran = man.beginTransaction();

        Fragment_one = new BeerTabs();
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString("beerID",b);
        editor.putString("breweryID",brewery);
        editor.commit();


        tran.replace(R.id.main, Fragment_one);//tran.
        tran.addToBackStack(null);
        tran.commit();





    }
}

由于生命周期的原因,片段必须有一个空的构造函数。 考虑用空的替换你得到的那个,然后通过 Bundle 传递 String scanContent。这样你就可以确保片段总是得到你的 scanContent 即使片段重新创建了自己。

Fragment fragment = new Fragment() {
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if(getArguments() != null) {
                String scanContent = getArguments().getString("scanContent");
            }
        }
    };

Bundle bundle = new Bundle();
bundle.putString("scanContent", scanContent);
fragment.setArguments(bundle);

编辑:

来自你的Activity

BarcodeFrag fragment = new BarcodeFrag();
Bundle bundle = new Bundle();
bundle.putString("scanContent", scanContent);
fragment.setArguments(bundle);

在您的 Fragment 上,替换

 public BarcodeFrag(String scanContent) {
    id = scanContent;
 }

public BarcodeFrag() {
}

并从 onCreateView(...) 得到 id 像这样:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if(id == null && getArguments() != null) {
        String scanContent = getArguments().getString("scanContent");
        this.id = scanContent;
    }
    .
    .
    .
    .
}

移除

public BarcodeFrag(String scanContent) {
    id = scanContent;
}

Android 中的 Fragment 不应该有非空的构造函数。相反,您可以在 Fragment 中创建一个 static 启动器工厂方法,如下所示:

public static final String SCAN_CONTENT = "param";
private String scanContent;

public static final BarcodeFrag instanceOf(String scanContent) {
    BarcodeFrag fragment = new BarcodeFrag();
    Bundle args = new Bundle();
    args.putString(SCAN_CONTENT, scanContent);
    fragment.setArguments(args);
    return fragment;
}

现在,从任何其他 class、

创建 BarcodeFrag 的新实例

Fragment f = BarcodeFrag.instanceOf(scanContent)

并访问 BarcodeFrag

内的值 scanContent

scanContent = getArguments().getString(SCAN_CONTENT);

传递的参数可以是任何类型,即intfloatString

试试这个。这应该有效;

如果没有定义构造函数,编译器会自动创建默认构造函数。

如果任何 带有参数 的构造函数是 defined.In 情况,如果您调用默认构造函数,那么它将给出编译时错误。

public class P2 {

    public P2(int a) {

    }

    public static void main(String[] args) {
        P2 p = new P2(10);
        P2 p1 = new P2(); //compile time error      
    }
}

为了消除编译时错误,也添加默认构造函数

public class P2 {

    public P2() { //After adding this constructor, compile time error is removed

    }
    public P2(int a) {

    }

    public static void main(String[] args) {
        P2 p = new P2(10);
        P2 p1 = new P2();       
    }
}