简体   繁体   English

如何在监听器中正确使用Bundles(匿名内部类)

[英]How to properly use Bundles within a listener (anonymous inner class)

I am having an issue with an app I am creating. 我正在创建的应用程序有问题。
I created a series of Fragments within a single main Activity. 我在一个主活动中创建了一系列片段。
In each Fragment is either a form for data collection, or a ListView for displaying the colelcted data. 在每个Fragment中,要么是用于数据收集的表单,要么是用于显示汇总数据的ListView。

The data manipulation is controlled by the listener methods of several widgets and the data model behind the scenes. 数据操作由几个小部件的侦听器方法以及幕后的数据模型控制。

Basically I am using the data collection Fragment to store data in an SQLite database, which is then queried upon travel to a display fragment. 基本上,我使用的是数据集合Fragment,将数据存储在SQLite数据库中,然后在访问显示片段时对其进行查询。 The display fragments have buttons for returning to the collection fragments to add, edit, or delete a selected item. 显示片段具有用于返回到集合片段以添加,编辑或删除所选项目的按钮。 In the case of an add/edit button press I would in certain states send a bundle which could be filled differently based on the needs of the user. 在按下添加/编辑按钮的情况下,我会在某些状态下发送一个捆绑包,该捆绑包可以根据用户的需求进行不同填充。 Typically a bundle contains information sent from a parent context to a child context upon which the child unpacks the bundle and places data in text fields and/or sets spinners containing static data. 通常,捆绑包包含从父上下文发送到子上下文的信息,子包在该子上下文上解压缩捆绑包并将数据放置在文本字段中和/或设置包含静态数据的微调框。

I tried using an over complicated approach where I created a new Bundle directly inside whatever widget listener was being used. 我尝试使用一种过于复杂的方法,即在使用的任何窗口小部件侦听器中直接创建一个新的Bundle。
But I found that it was creating unnecessary complexity in the following Fragment where I would need to test for keys contained within the Bundles from several different possible origins. 但是我发现在下面的片段中创建了不必要的复杂性,在该片段中,我需要测试来自多个不同来源的捆绑包中包含的密钥。

The thought was that inside the beginning of any Fragment I would call 我的想法是,在我会称呼的任何片段的开头

Bundle bundle = this.getArguments()

Which would set bundle to whichever Bundle was passed in: 哪个将bundle设置为传入的Bundle:

fragment.setArguments(*bundle based on conditions*)

so from this flow I had to create an incredibly long and hard to read succession of if-conditionals looking for specific keys based on bundle.isEmpty() which of course throws a NullPointerException if you're arriving at that Fragment for the first time and no bundle has been sent yet. 因此,从这个流程中,我不得不创建难以置信的冗长且难以阅读的if条件,以基于bundle.isEmpty()寻找特定键,如果您是第一次到达该Fragment,则当然会抛出NullPointerException,并且尚未发送捆绑。
Then to compound the nightmare I threw all of this in a try-catch to handle the bundle.isEmpty() null pointer, which, I tried to use as an indicator of current state (/sigh... I know). 然后,为了解决这个噩梦,我将所有这些内容都放入try-catch中以处理bundle.isEmpty()空指针,我试图将其用作当前状态的指示器(/ sigh ...我知道)。

What I would like to do is use Bundle savedInstanceState for any traffic of info/state to a new Fragment. 我想做的是将Bundle savedInstanceState用于到新Fragment的任何信息/状态通信。
So ideally I would only ever have to access one Bundle and test for containing keys. 因此,理想情况下,我只需要访问一个捆绑包并测试是否包含密钥。
Then it seems that I would be able to test for whether or not savedInstanceState is null and set it somehow. 然后看来,我将能够测试savedInstanceState是否为null并以某种方式进行设置。

The problem is that I have these widgets in my Fragments which I am using to interact with my model and possibly navigate to the next necessary Fragment. 问题是我的片段中有这些小部件,这些小部件可用于与模型交互并可能导航到下一个必要的片段。
If I use savedInstanceState within an onClick listener method of one of the widgets, I am forced to make it final which promptly removes my ability to use savedInstanceState in any other scope but the initial usage of it or at least that is my understanding. 如果我在其中一个小部件的onClick侦听器方法中使用了savedInstanceState ,则必须将其设置为final ,这会立即删除我在除其他用法之外的其他范围内使用savedInstanceState能力,至少这是我的理解。
This causes NullPointerException errors when I try to access savedInstanceState outside of the first scope. 当我尝试访问第一个作用域之外的savedInstanceState时,这将导致NullPointerException错误。

If I remove final the IDE tells me (correctly so) that I cannot access savedInstanceState from within an inner class, which in my case is several widgets to which I have attached listener methods. 如果我删除了final那么IDE会告诉我(正确地如此),我无法从内部类中访问savedInstanceState ,在我的情况下,这是我已将其附加到侦听器方法的几个小部件。

I have read: 我读过了:

Are the bundles in android permanent in saving activity states ? android中的捆绑包是否永久保存活动状态?

How to use the anonymous inner class? 如何使用匿名内部类?

How to use Outer Method's input in Anonymous Inner Class? 如何在匿名内部类中使用外部方法的输入?

Here is a code example of two Fragments reliant upon sending Bundles to each other; 这是两个相互依赖发送Bundle的Fragment的代码示例;

The display and select class: 显示和选择类:

public class Row_main extends Fragment {

Spinner location_spinner;
Button add_row_btn,edit_row_button,delete_row_btn;

ListView row_list_holder;

StorageHandler sh;
List<Row> row_list;

ArrayAdapter<CharSequence> ls_adapter;
String [] location_test_values = {"test_location"};


boolean has_items;

public Row_main()
{
    //default constructor
}

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


    if(savedInstanceState == null)
    {
        //this will satisfy if arriving here from navigation menu.
        //I would like to set savedInstanceState here if null.
        savedInstanceState = new Bundle();
        //but I get error: 'cannot assign a value to final variable'
    }

    getActionBar().setTitle("Row");

    //Create view
    final View v = inflater.inflate(R.layout.row_main_layout, container, false);

    add_row_btn = (Button) v.findViewById(R.id.add_row_btn);
    edit_row_button = (Button) v.findViewById(R.id.edit_row_btn);
    delete_row_btn = (Button) v.findViewById(R.id.delete_row_btn);

    add_row_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            addRow fragment = new addRow();

            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            fragment.setArguments(savedInstanceState);
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();

            getActionBar().setTitle("Add Row");
        }
    });

    edit_row_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            for(int i=0; i<row_list.size(); i++)
            {
                if(row_list.get(i).isSelected())
                {
                    row_list.get(i).setEdited(true);

                    addRow fragment = new addRow();

                    savedInstanceState.putStringArrayList("current_row",row_list.get(i).getList());

                    fragment.setArguments(savedInstanceState);

                    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
                    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                    fragmentTransaction.replace(R.id.fragment_container, fragment);
                    fragmentTransaction.addToBackStack(null);
                    fragmentTransaction.commit();
                    getActionBar().setTitle("Add Row");
                }
            }
        }
    });

    return v;
}

private ActionBar getActionBar() {
    return ((AppCompatActivity) getActivity()).getSupportActionBar();
}

and here is the data collect form class: 这是数据收集表单类:

public class addRow extends Fragment {

IdGenerator generator;

String new_id;

AlertDialog.Builder alertDialogBuilder, fmdDialogBuilder;

EditText row_name,
         rack_name,
         tile_location,
         tile_name,
         separation,
         bf_offset;

Spinner object_type,
        direction,
        rotation;

ArrayAdapter<CharSequence> objType_adapter,
                     direction_adapter,
                     rotation_adapter;

String[] objtype_values = {"Rack","FMD"};
String[] direction_values = {"Right","Left"};
String[] rotation_values = {"0","90","180","270"};

int RACK = 0,FMD = 1,RIGHT = 0,LEFT = 1;

Row current_row;

ArrayList<String> list_to_unpack;

Button  save_row_btn,
        add_btn,
        cancel_btn;

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


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

    generator = new IdGenerator();
    new_id = generator.randomString(5);

    if(savedInstanceState != null)
    {
        //Bundle passed, edit button was used, unpack
        if (savedInstanceState.containsKey("current_row")) {
            Log.d("BUNDLE-CONTENTS", "" + savedInstanceState.size());

            list_to_unpack = savedInstanceState.getStringArrayList("current_row");

            current_row.setId(list_to_unpack.get(0));
            current_row.setRow_name(list_to_unpack.get(1));
            current_row.setObject_type(list_to_unpack.get(2));
            current_row.setRack_name(list_to_unpack.get(3));
            current_row.setTile_location(list_to_unpack.get(4));
            current_row.setTile_name(list_to_unpack.get(5));
            current_row.setDirection(list_to_unpack.get(6));
            current_row.setRotation(list_to_unpack.get(7));
            current_row.setSeparation(list_to_unpack.get(8));
            current_row.setBf_offset(list_to_unpack.get(9));
            current_row.setEdited(true);

            row_name.setText(current_row.getRow_name());

            if (current_row.getObject_type().equalsIgnoreCase("Rack")) {
                object_type.setSelection(RACK);
            } else {
                object_type.setSelection(FMD);
            }

            rack_name.setText(current_row.getRack_name());

            tile_location.setText(current_row.getTile_location());

            tile_name.setText(current_row.getTile_name());

            if (current_row.getDirection().equalsIgnoreCase("Right")) {
                direction.setSelection(RIGHT);
            } else {
                direction.setSelection(LEFT);
            }

            switch(current_row.getRotation())
            {
                case "0": rotation.setSelection(0); break;
                case "90": rotation.setSelection(1); break;
                case "180": rotation.setSelection(2); break;
                case "270": rotation.setSelection(3); break;
            }

            separation.setText(current_row.getSeparation());

            bf_offset.setText(current_row.getBf_offset());
        }
    }

    row_name = (EditText) v.findViewById(R.id.rowName_value);
    rack_name = (EditText) v.findViewById(R.id.rackName_value);
    tile_location = (EditText) v.findViewById(R.id.tileLoc_value);
    tile_name = (EditText) v.findViewById(R.id.tileName_value);
    separation = (EditText) v.findViewById(R.id.separation_value);
    bf_offset = (EditText) v.findViewById(R.id.bfOffset_value);

    object_type = (Spinner) v.findViewById(R.id.obj_type);
    direction = (Spinner) v.findViewById(R.id.direction);
    rotation = (Spinner) v.findViewById(R.id.rotation_spinner);

    objType_adapter = new ArrayAdapter<CharSequence>(this.getActivity(),
            android.R.layout.simple_spinner_dropdown_item, objtype_values);
    direction_adapter = new ArrayAdapter<CharSequence>(this.getActivity(),
            android.R.layout.simple_spinner_dropdown_item, direction_values);
    rotation_adapter = new ArrayAdapter<CharSequence>(this.getActivity(),
            android.R.layout.simple_spinner_dropdown_item, rotation_values);

    object_type.setAdapter(objType_adapter);
    direction.setAdapter(direction_adapter);
    rotation.setAdapter(rotation_adapter);

    save_row_btn = (Button) v.findViewById(R.id.save_row_btn);
    add_btn = (Button) v.findViewById(R.id.add_btn);
    cancel_btn = (Button) v.findViewById(R.id.cancel_btn);

    alertDialogBuilder = new AlertDialog.Builder(getActivity());
    fmdDialogBuilder = new AlertDialog.Builder(getActivity());

    alertDialogBuilder.setMessage("Add Rack or FMD:");
    fmdDialogBuilder.setMessage("Add Power Providing or Power Consuming FMD:");

    alertDialogBuilder.setNegativeButton("Rack", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            //if user selects power providing fmd
            //send id with it
            //StorageHandler sh = new StorageHandler(getActivity());

            Row row = new Row(
                    new_id,
                    row_name.getText().toString(),
                    object_type.getSelectedItem().toString(),
                    rack_name.getText().toString(),
                    tile_location.getText().toString(),
                    tile_name.getText().toString(),
                    direction.getSelectedItem().toString(),
                    rotation.getSelectedItem().toString(),
                    separation.getText().toString(),
                    bf_offset.getText().toString());



            ArrayList<String> rowList = row.getList();

            for(String i : rowList)
            {
                Log.d("ADD ROW BTN","rowList[i]=" + i);
            }

            savedInstanceState.putStringArrayList("current_row", rowList);

            addRack fragment = new addRack();
            fragment.setArguments(savedInstanceState);
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
            getActionBar().setTitle("Add Rack to: " + row.getRow_name());
        }
    });

    alertDialogBuilder.setPositiveButton("FMD", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            //todo choice between consuming and providing
            fmdDialogBuilder.show();
        }
    });

    fmdDialogBuilder.setPositiveButton("Providing", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {

            Row row = new Row(
                    new_id,
                    row_name.getText().toString(),
                    object_type.getSelectedItem().toString(),
                    rack_name.getText().toString(),
                    tile_location.getText().toString(),
                    tile_name.getText().toString(),
                    direction.getSelectedItem().toString(),
                    rotation.getSelectedItem().toString(),
                    separation.getText().toString(),
                    bf_offset.getText().toString());

            ArrayList<String> obj_as_list = row.getList();

            Log.d("newId", obj_as_list.get(0));
            Log.d("row_name", obj_as_list.get(1));
            Log.d("object_type", obj_as_list.get(2));
            Log.d("rack_name", obj_as_list.get(3));
            Log.d("objaslistsize", ""+obj_as_list.size());

            savedInstanceState.putStringArrayList("current_row", obj_as_list);

            addPowerProvidingFMD fragment = new addPowerProvidingFMD();

            fragment.setArguments(savedInstanceState);
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
            getActionBar().setTitle("add FMD to: " + row_name.getText().toString());
        }
    });

    fmdDialogBuilder.setNegativeButton("Consuming", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {

            Row row = new Row(
                    new_id,
                    row_name.getText().toString(),
                    object_type.getSelectedItem().toString(),
                    rack_name.getText().toString(),
                    tile_location.getText().toString(),
                    tile_name.getText().toString(),
                    direction.getSelectedItem().toString(),
                    rotation.getSelectedItem().toString(),
                    separation.getText().toString(),
                    bf_offset.getText().toString());

            ArrayList<String> obj_as_list = row.getList();

            savedInstanceState.putStringArrayList("current_row", obj_as_list);

            addPowerConsumingFMD fragment = new addPowerConsumingFMD();
            fragment.setArguments(savedInstanceState);
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
            getActionBar().setTitle("add FMD to: " + row_name.getText().toString());
        }
    });

    save_row_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //save row info to database
            StorageHandler sh = new StorageHandler(getActivity());

            if(current_row.isEdited())
            {
                //update row
                String current_id = current_row.getId();
                Log.d("*update row*", "id=" + current_id);

                //get updated values from fields, send to database
                Row row = new Row(current_id, row_name.getText().toString(), object_type.getSelectedItem().toString(),
                        rack_name.getText().toString(), tile_location.getText().toString(),
                        tile_name.getText().toString(), direction.getSelectedItem().toString(),
                        rotation.getSelectedItem().toString(), separation.getText().toString(),
                        bf_offset.getText().toString());

                sh.updateRow(row);

                sh.close();
            }
            else
            {
                //save new row
                Log.d("*save row*", "id=" + new_id);

                //save row to database
                sh.addRow(new Row(new_id, row_name.getText().toString(), object_type.getSelectedItem().toString(),
                        rack_name.getText().toString(), tile_location.getText().toString(),
                        tile_name.getText().toString(), direction.getSelectedItem().toString(),
                        rotation.getSelectedItem().toString(), separation.getText().toString(),
                        bf_offset.getText().toString()));

                sh.close();
            }

            Row_main fragment = new Row_main();
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
            getActionBar().setTitle("Row");
        }
    });

    add_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
             alertDialogBuilder.show();
        }
    });

    cancel_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Row_main fragment = new Row_main();
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
            getActionBar().setTitle("Row");
        }
    });

    return v;
}

private ActionBar getActionBar() {
    return ((AppCompatActivity) getActivity()).getSupportActionBar();
}

I would like to use Bundles here since it is not important to restore anything from a Bundle if the user leaves the app or presses the back Button. 我想在这里使用Bundles,因为如果用户离开应用程序或按下后退按钮,从Bundle中还原任何内容并不重要。

Am I going about this right? 我要这样做吗? what should I do about the final Bundle situation in onClickListener methods? 我应该如何处理onClickListener方法中的最终捆绑情况? I absolutely need to pass Bundles from them the way I have things setup now and I would like to use the same Bundle if I can. 我绝对需要以现在设置的方式从它们中传递Bundle,如果可以的话,我想使用相同的Bundle。

I have a deadline to consider so a complete overhaul might be out of the question. 我有一个最后期限要考虑,因此可能无法进行全面检修。

Any input is greatly appreciated. 任何输入,不胜感激。

I think it'll be easier to isolate your data-passing problems once you refactor some code. 我认为一旦重构某些代码,隔离数据传递问题会更容易。


1. Replace these similar blocks with a method. 1.用一种方法替换这些相似的块。 You seem to have copied this same chuck of code about five times. 您似乎已经复制了相同的代码约五次。

Make it a method! 使其成为一种方法! Call it getRow() , give it a parameter, if you have to, like for the int id . 调用它getRow() ,如果需要的话给它一个参数,例如int id

// int id = <some_value>;

return new Row(id, row_name.getText().toString(), object_type.getSelectedItem().toString(),
        rack_name.getText().toString(), tile_location.getText().toString(),
        tile_name.getText().toString(), direction.getSelectedItem().toString(),
        rotation.getSelectedItem().toString(), separation.getText().toString(),
        bf_offset.getText().toString());

2. Now, it seems you are passing around this Row class, so suggested to make that implement Parcelable so you can more easily pass that between Bundle s when the need arises. 2.现在,似乎您正在传递此Row类,因此建议使该实现Parcelable成为可能,以便在需要时可以在Bundle之间更轻松地传递它。


3. Next, you should let the Fragment interactions happen across the Activity boundary , not from within each Fragment. 3.接下来,您应该让Fragment交互跨活动边界发生 ,而不是在每个Fragment内进行。 So, you add interfaces, for example. 因此,例如,您添加接口。 You can split this into many interfaces, if you do not need all this functionality. 如果不需要所有这些功能,则可以将其拆分为许多接口。

public interface OnRowInteractionListener {
    public void onRowAdded(Row row);
    public void onRowEdited(Row row);
    public void onRowRemoved(Row row);
    public void onRowActionCancel();
}

3a. 3a。 Implement onAttach of the Fragment class(es) to set these interfaces. 实现Fragment类的onAttach来设置这些接口。

private OnRowInteractionListener mListener;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    final String contextName = context.class.getSimpleName();
    try {
        mListener = (OnRowInteractionListener) context;
    } catch (ClassCastException e) {
        throw new ClassCastException(contextName + " must implement OnRowInteractionListener");
    }
}

3b. 3b。 Now, clean up the Fragment buttons 现在,清理“片段”按钮

add_row_btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Row added = getRow(); // remember about that parameter value
        if (mListener != null) mListener.onRowAdded(added);
    }
});

3c. 3c。 In the Activity, you need to implement those interfaces after you make the class implements OnRowInteractionListener . 在Activity中,需要在使类implements OnRowInteractionListener之后实现这些接口。

@Override
public void onRowAdded(Row row) { 

    getActionBar().setTitle("Add Row");

    // This acts like your 'constructor'
    AddRowFragment fragment = AddRowFragment.newInstance(row);
    // fragment.setArguments(savedInstanceState);

    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .addToBackStack(null)
            .commit();
}

(similar for onRowEdited ) (与onRowEdited类似)


4. I also see this Fragment replacement block of code repeated for cancel and save buttons, so make that a method as well. 4.我还看到针对取消和保存按钮重复执行此Fragment替换代码块,因此也使该方法成为可能。

Row_main fragment = new Row_main();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
getActionBar().setTitle("Row");

I would really suggest you make one really generic method in the Activity to handle all Fragment transitions. 我真的建议您在Activity中制作一个真正通用的方法来处理所有Fragment过渡。

public void transitionFragment(Fragment fragment, Bundle arguments, String title) { 

    getSupportActionBar().setTitle(title);

    if (arguments != null) fragment.setArguments(arguments);

    getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .addToBackStack(null)
            .commit();
}

Then, just pass in the respective newInstance() 'd Fragment to that method whenever you need it. 然后,只要需要,只需将相应的newInstance() 'd片段传递给该方法即可。 Optionally pass extra arguments, else, just null . (可选)传递额外的参数,否则为null

So, then, you now can use that method for the previous block of code, for example, in the cancel action of the interface implementation. 因此,现在,您可以将该方法用于前面的代码块,例如,在接口实现的cancel动作中。

@Override
public void onRowActionCancel() {
    Fragment fragment = RowMainFragment.newInstance();
    transitionFragment(fragment, null, "Add Row");
}

As far as the SQLite processing goes, maybe look into RealmDB, SugarORM, or really any ORM library. 就SQLite处理而言,也许可以研究RealmDB,SugarORM或任何ORM库。

The findViewById code could be simplified with Butterknife. 可以使用Butterknife简化findViewById代码。 Also, the Android Data Binding library in case you are frequently mapping data to the View objects from a Java object. 另外,如果您经常将数据从Java对象映射到View对象,则可以使用Android数据绑定库

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用匿名内部类? - How to use the anonymous inner class? 定义为匿名内部类的Java事件侦听器如何使用封闭类中的变量? - How can an java event listener defined as an anonymous inner class use a variable from an enclosing class? 如何在匿名内部类中使用外部变量 - How to use an outer variable in an anonymous inner class 访问匿名或本地内部类中的匿名或本地内部类 - Access an Anonymous or Local Inner Class Within an Anonymous or Local Inner Class 在匿名内部类android中更新适配器 - updating adapter within anonymous inner class android 在匿名内部类中修改外部变量 - Modifying an outer variable within an anonymous inner class 如何在 kotlin 中使用 lambda 进行匿名内部类替换 - How to use lambda in kotlin for anonymous inner class replacement 如何在匿名内部类中使用外部方法的输入? - How to use Outer Method's input in Anonymous Inner Class? 如何在匿名内部 class 中使用 Assert.assertTrue? - How to use Assert.assertTrue in anonymous inner class? 如何正确设置匿名类中的字段并在主类中使用它们? - How properly set fields in anonymous class and use them in main class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM