简体   繁体   English

为什么最终变量没有内部类就返回?

[英]Why final variable return without inner class?

I want to return final ArrayList in Android, but the ArrayList always return size 0. I do add() in inner class, but the return log faster then inner class log. 我想在Android中返回final ArrayList ,但ArrayList始终返回大小0。我在内部类中执行add() ,但是返回日志要比内部类日志快。

My code : 我的代码:

public static ArrayList<SportsData> getSportsFavorite(){
    final ArrayList<SportsData> sportsDatas = new ArrayList<>();

    DBRequestData reqData = new DBRequestData();
    reqData.cmdId = CmdConst.DISCIPLINE_DATA.SELECT_ALL.ordinal();
    DisciplineCmd cmd = new DisciplineCmd();
    cmd.requestCmd(reqData, new OnDatabaseListener() {
        @Override
        public void onDBResponse(BaseCmd command) {
            if (command == null || command.getResponseData() == null) {
                return;
            }

            ArrayList<DisciplineTable> dbDisciplineList = command.getResponseData().disciplineTableList;
            if (dbDisciplineList == null) {
                return;
            }

            if(sportsFavoriteList.size() == 0) {
                init();
            }

            for (DisciplineTable disciplineData : dbDisciplineList){
                for (String favoriteCode : sportsFavoriteList){
                    String[] codeArr = favoriteCode.split("[|]");
                    String discCode = codeArr[0];
                    String compeCode = codeArr[1];

                    if(disciplineData.disciplineCode.equals(discCode) && disciplineData.competitionCode.equals(compeCode)){
                        int imgRes = SportsUtil.getSportsImgResource(disciplineData.disciplineCode, disciplineData.competitionCode);
                        sportsDatas.add(new SportsData(imgRes, disciplineData));
                        Log.e("SportsUtil", "inner Size : "+sportsDatas.size()); // RETURN SECOND -
                    }
                }
            }
        }
    });

    Log.e("SportsUtil", "Return Size : "+sportsDatas.size()); //RETURN FIRST
    return sportsDatas;
}

Logcat : Logcat:

07-22 14:33:32.337      651-651/com.samsung.riowow.result E/SportsUtil﹕ Return Size : 0
07-22 14:33:32.347      651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 1
07-22 14:33:32.347      651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 2
07-22 14:33:32.347      651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 3
07-22 14:33:32.347      651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 4
07-22 14:33:32.347      651-651/com.samsung.riowow.result E/SportsUtil﹕ inner Size : 5

The result that want to is ArrayList what size is 5. But always return ArrayList 's size is 0. Please help me :) Thanks. 想要的结果是ArrayList大小是5。但是总是返回ArrayList的大小是0。请帮助我:)谢谢。



SOLVE 解决

If you want to know reason of this situation, please check the Florian Schaetz's answer. 如果您想知道这种情况的原因,请检查Florian Schaetz的回答。

My solution for this, I change the return type of method and add interface listener parameter. 为此,我更改了方法的返回类型并添加了interface侦听器参数。 Please check my solution. 请检查我的解决方案。

First, Create interface and method has parameter you want to return. 首先,Create接口和方法具有要返回的参数。

public static interface SportsDataListener{
    public void onSportsDataResponse(ArrayList<SportsData> sportsDataList);
}

Second, Change method's return type to void and add interface parameter. 其次,将方法的返回类型更改为void并添加接口参数。 And call interface's method instead return 而调用接口的方法反而返回

public static void getSportsFavorite(final SportsDataListener listener){
    final ArrayList<SportsData> sportsDatas = new ArrayList<>();
    DBRequestData reqData = new DBRequestData();
    reqData.cmdId = CmdConst.DISCIPLINE_DATA.SELECT_ALL.ordinal();
    DisciplineCmd cmd = new DisciplineCmd();
    cmd.requestCmd(reqData, new OnDatabaseListener() {
        @Override
        public void onDBResponse(BaseCmd command) {
            if (command == null || command.getResponseData() == null) {
                return;
            }

            ArrayList<DisciplineTable> dbDisciplineList = command.getResponseData().disciplineTableList;
            if (dbDisciplineList == null) {
                return;
            }

            if(sportsFavoriteList.size() == 0) {
                init();
            }

            for (DisciplineTable disciplineData : dbDisciplineList){
                for (String favoriteCode : sportsFavoriteList){
                    String[] codeArr = favoriteCode.split("[|]");
                    String discCode = codeArr[0];
                    String compeCode = codeArr[1];

                    if(disciplineData.disciplineCode.equals(discCode) && disciplineData.competitionCode.equals(compeCode)){
                        int imgRes = SportsUtil.getSportsImgResource(disciplineData.disciplineCode, disciplineData.competitionCode);
                        sportsDatas.add(new SportsData(imgRes, disciplineData));
                    }
                }
            }
            listener.onSportsDataResponse(sportsDatas);
        }
    });
}

Last, You can use 最后,您可以使用

SportsUtil.getSportsFavorite(new SportsUtil.SportsDataListener() {
    @Override
    public void onSportsDataResponse(ArrayList<SportsData> sportsDataList) {
        //Some action you want to do. You can use parameter
    }
}

Seems pretty asynchronous to me. 对我来说似乎很异步。 You are calling a method and give it a callback that will be called AFTER the action is done, here probably after the database returns. 您正在调用一个方法,并给它一个回调,该回调将在操作完成后调用,这里可能是在数据库返回之后。 The main code isn't blocked, but goes one, while the other OnDatabaseListener waits in the background for an answer, thus your method returns the original list which then suddenly grows as the database answer returns. 主代码没有被阻止,而是进入一个,而另一个OnDatabaseListener则在后台等待答案,因此您的方法返回原始列表,然后该列表随着数据库答案的返回而突然增长。

I guess your onDBResponse method is running in different thread. 我猜你的onDBResponse方法在不同的线程中运行。 You are modifying the arraylist inside that method. 您正在该方法内修改arraylist。 So before modifying the arraylist is getting returned in this case. 因此,在这种情况下,在修改arraylist之前将其返回。 Always it will give you arraylist of size 0. 始终它将为您提供大小为0的arraylist。

您应该为getSportsFavorite()提供一个回调接口,该接口将数组列表作为参数,并在OnDatabaseListener方法完成时调用它。

Yes the problem is because your onDBResponse() is called after the method has returned the array list. 是的,问题是因为在方法返回数组列表之后调用了onDBResponse()。 You should suspect this from the order of your logs. 您应该从日志顺序中怀疑这一点。

SOLUTION

Assuming that it is your requirement that you get the array list synchronously. 假设您需要同步获取数组列表。 Just before your cmd.requestCmd do: 就在您的cmd.requestCmd做之前:

final Object lock = new Object();

then add this before your return sportsDatas; 然后在您return sportsDatas;之前添加它return sportsDatas; :

synchronized(lock) {
    lock.wait();
}

and in the end of onDBResponse() add: onDBResponse()的末尾添加:

synchronized(lock) {
    lock.notify();
}

Essentially, now your method will wait until the response from DB has come before returning the array list. 从本质上讲,现在您的方法将等到DB的响应到来之后再返回数组列表。

You will need to catch the InterruptedException and that's it! 您将需要捕获InterruptedException就是这样! Hope it helps! 希望能帮助到你! :) :)

you must run onDBResponse once at least. 您必须至少运行一次onDBResponse。

public static void main(String[] args) {
    final List<String> sportsDatas = new ArrayList<>();
    Commond commond = new Commond() {
        @Override
        public void onDBResponse() {
            sportsDatas.add("1");
            sportsDatas.add("2");
            sportsDatas.add("3");
        }
    };
    System.out.println(sportsDatas.size());

    commond.onDBResponse();

    System.out.println(sportsDatas.size());
    }
}

output: 输出:

0
3

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM